Compare commits

...

1452 Commits

Author SHA1 Message Date
Rob Bradford
bb02c28b62 build: Update for v0.14.1 bug fix release
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-31 16:56:05 +01:00
Sebastien Boeuf
b2c96dea24 vmm: Add missing syscall for vCPU unplug
clock_nanosleep() is triggered when hot-unplugging a vCPU.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
(cherry picked from commit 46f96f27a4)
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-31 16:56:05 +01:00
Rob Bradford
2c81312433 vm-virtio: queue: Fix descriptor chain validation
DescriptorChain::is_valid() wrongly used .checked_offset() to attempt to
validate that the descriptor's data is in valid memory. This works in
all cases except where the guest has placed the data at the very end of
the guest memory as the offset + offset will be outside the range (as
the combined offset will be the next byte and as such out of the guest
memory). Instead use the function .check_range() takes an offset and a
length to validate

This fixes issues see with error messages featuring the
DescriptorChainTooShort error.

Fixes: #2424

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
(cherry picked from commit 1eb4ebe3d1)
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-31 16:56:05 +01:00
Anatol Belski
e8ee29b4fe CpuManager: Fix MMIO read handling
There are two parts:

- Unconditionally zero the output area. The length of the incoming
  vector has been seen from 1 to 4 bytes, even though just the first
  byte might need to be handled. But also, this ensures any possibly
  unhandled offset will return zeroed result to the caller. The former
  implementation used an I/O port which seems to behave differently from
  MMIO and wouldn't require explicit output zeroing.
- An access with zero offset still takes place and needs to be handled.

Fixes #2437.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
(cherry picked from commit 9e9aba7c0b)
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-31 16:56:05 +01:00
Anatol Belski
498939c297 hyperv: Fix CPU hotadd
The following is from the Hyper-V specification v6.0b.

Cpuid leaf 0x40000003 EDX:

Bit 3: Support for physical CPU dynamic partitioning events is
available.

When Windows determines to be running under a hypervisor, it will
require this cpuid bit to be set to support dynamic CPU operations.

Cpuid leaf 0x40000004 EAX:

Bit 5: Recommend using relaxed timing for this partition. If
used, the VM should disable any watchdog timeouts that
rely on the timely delivery of external interrupts.

This bit has been figured out as required after seeing guest BSOD
when CPU hotplug bit is enabled. Race conditions seem to arise after a
hotplug operation, when a system watchdog has expired.

Closes #1799.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
(cherry picked from commit 5b168f54a6)
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-31 16:56:05 +01:00
Rob Bradford
84b3992146 build: Update Cargo.lock for release
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:46:55 +00:00
Rob Bradford
40c63dcf5e build: Update for 0.14.0 release
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:27 +00:00
Rob Bradford
970bc05271 aarch64: Address Rust 1.51.0 clippy issue (vec_init_then_push)
--> arch/src/aarch64/mod.rs:82:5
    |
82  | /     let mut regions = Vec::new();
83  | |     // 0 ~ 256 MiB: Reserved
84  | |     regions.push((
85  | |         GuestAddress(0),
...   |
107 | |         RegionType::Ram,
108 | |     ));
    | |_______^ help: consider using the `vec![]` macro: `let mut regions = vec![..];`
    |
    = note: `-D clippy::vec-init-then-push` implied by `-D warnings`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#vec_init_then_push

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
4da6bcd5d5 aarch64: Address Rust 1.51.0 clippy issue (from_over_into)
error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
Error:   --> devices/src/legacy/rtc_pl031.rs:73:1
   |
73 | impl Into<libc::clockid_t> for ClockType {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `-D clippy::from-over-into` implied by `-D warnings`
   = help: consider to implement `From` instead
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
3671f5e94c aarch64: Address Rust 1.51.0 clippy issue (redundant_slicing)
error: redundant slicing of the whole range
Error:    --> devices/src/legacy/gpio_pl061.rs:298:37
    |
298 |             let value = read_le_u32(&data[..]);
    |                                     ^^^^^^^^^ help: use the original slice instead: `data`
    |
    = note: `-D clippy::redundant-slicing` implied by `-D warnings`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
40da6210f4 aarch64: Address Rust 1.51.0 clippy issue (upper_case_acroynms)
error: name `GPIOInterruptDisabled` contains a capitalized acronym

Error:   --> devices/src/legacy/gpio_pl061.rs:46:5
   |
46 |     GPIOInterruptDisabled,
   |     ^^^^^^^^^^^^^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `GpioInterruptDisabled`
   |
   = note: `-D clippy::upper-case-acronyms` implied by `-D warnings`
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
3c6dfd7709 tdx: Address Rust 1.51.0 clippy issue (upper_case_acroynms)
error: name `FinalizeTDX` contains a capitalized acronym
   --> vmm/src/vm.rs:274:5
    |
274 |     FinalizeTDX(hypervisor::HypervisorVmError),
    |     ^^^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `FinalizeTdx`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
e294688904 hypervisor: Address Rust 1.51.0 clippy issue (from_over_into)
warning: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
  --> hypervisor/src/vm.rs:41:1
   |
41 | impl Into<u64> for DataMatch {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(clippy::from_over_into)]` on by default
   = help: consider to implement `From` instead
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into

warning: 1 warning emitted

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
5c010d489d tests: Address Rust 1.51.0 clippy issue (needless_question_mark)
error: Question mark operator is useless here
   --> tests/integration.rs:494:13
    |
494 | /             Ok(self
495 | |                 .ssh_command("grep MemTotal /proc/meminfo | grep -o \"[0-9]*\"")?
496 | |                 .trim()
497 | |                 .parse()
498 | |                 .map_err(Error::Parsing)?)
    | |__________________________________________^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
c5d15fd938 devices: Address Rust 1.51.0 clippy issue (upper_case_acroynms)
warning: name `AcpiPMTimerDevice` contains a capitalized acronym
   --> devices/src/acpi.rs:175:12
    |
175 | pub struct AcpiPMTimerDevice {
    |            ^^^^^^^^^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `AcpiPmTimerDevice`
    |
    = note: `#[warn(clippy::upper_case_acronyms)]` on by default
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
827229d8e4 pci: Address Rust 1.51.0 clippy issue (upper_case_acroynms)
warning: name `IORegion` contains a capitalized acronym
   --> pci/src/configuration.rs:320:5
    |
320 |     IORegion = 0x01,
    |     ^^^^^^^^ help: consider making the acronym lowercase, except the initial letter (notice the capitalization): `IoRegion`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
6837de9057 vmm: Address Rust 1.51.0 clippy issue (upper_case_acroynms)
warning: name `ConvertFromUTF8` contains a capitalized acronym
  --> virtio-devices/src/vsock/unix/mod.rs:32:5
   |
32 |     ConvertFromUTF8(std::str::Utf8Error),
   |     ^^^^^^^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `ConvertFromUtf8`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
7c9a83f6e1 virtio-devices: Address Rust 1.51.0 clippy issue (needless_question_mark)
warning: Question mark operator is useless here
   --> virtio-devices/src/seccomp_filters.rs:485:5
    |
485 | /     Ok(SeccompFilter::new(
486 | |         rules.into_iter().collect(),
487 | |         SeccompAction::Log,
488 | |     )?)
    | |_______^
    |
    = note: `#[warn(clippy::needless_question_mark)]` on by default
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark
help: try
    |
485 |     SeccompFilter::new(
486 |         rules.into_iter().collect(),
487 |         SeccompAction::Log,
488 |     )
    |

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
2571cc8041 virtio-devices: Address Rust 1.51.0 clippy issue (vec_init_then_push)
warning: calls to `push` immediately after creation
   --> virtio-devices/src/vhost_user/net.rs:291:13
    |
291 | /             let mut interrupt_list_sub: Vec<(Option<EventFd>, Queue)> = Vec::with_capacity(2);
292 | |             interrupt_list_sub.push(vu_interrupt_list.remove(0));
293 | |             interrupt_list_sub.push(vu_interrupt_list.remove(0));
    | |_________________________________________________________________^ help: consider using the `vec![]` macro: `let mut interrupt_list_sub: Vec<(Option<EventFd>, Queue)> = vec![..];`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#vec_init_then_push

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
3b8d1f1411 vmm: Address Rust 1.51.0 clippy issue (vec_init_then_push)
warning: calls to `push` immediately after creation
   --> vmm/src/cpu.rs:630:9
    |
630 | /         let mut cpuid_patches = Vec::new();
631 | |
632 | |         // Patch tsc deadline timer bit
633 | |         cpuid_patches.push(CpuidPatch {
...   |
662 | |             edx_bit: Some(MTRR_EDX_BIT),
663 | |         });
    | |___________^ help: consider using the `vec![]` macro: `let mut cpuid_patches = vec![..];`
    |
    = note: `#[warn(clippy::vec_init_then_push)]` on by default
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#vec_init_then_push

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
9762c8bc28 vmm: Address Rust 1.51.0 clippy issue (upper_case_acroynms)
warning: name `LocalAPIC` contains a capitalized acronym
   --> vmm/src/cpu.rs:197:8
    |
197 | struct LocalAPIC {
    |        ^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `LocalApic`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
7c302373ed vmm: Address Rust 1.51.0 clippy issue (needless_question_mark)
warning: Question mark operator is useless here
   --> vmm/src/seccomp_filters.rs:493:5
    |
493 | /     Ok(SeccompFilter::new(
494 | |         rules.into_iter().collect(),
495 | |         SeccompAction::Trap,
496 | |     )?)
    | |_______^
    |
    = note: `#[warn(clippy::needless_question_mark)]` on by default
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark
help: try
    |
493 |     SeccompFilter::new(
494 |         rules.into_iter().collect(),
495 |         SeccompAction::Trap,
496 |     )
    |

warning: Question mark operator is useless here
   --> vmm/src/seccomp_filters.rs:507:5
    |
507 | /     Ok(SeccompFilter::new(
508 | |         rules.into_iter().collect(),
509 | |         SeccompAction::Log,
510 | |     )?)
    | |_______^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark
help: try
    |
507 |     SeccompFilter::new(
508 |         rules.into_iter().collect(),
509 |         SeccompAction::Log,
510 |     )
    |

warning: Question mark operator is useless here
   --> vmm/src/vm.rs:887:9
    |
887 |         Ok(CString::new(cmdline).map_err(Error::CmdLineCString)?)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `CString::new(cmdline).map_err(Error::CmdLineCString)`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
19c5e91b6e main: Address Rust 1.51.0 clippy issue (upper_case_acroynms)
warning: name `StartVMMThread` contains a capitalized acronym
  --> src/main.rs:50:5
   |
50 |     StartVMMThread(#[source] vmm::Error),
   |     ^^^^^^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `StartVmmThread`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
4a5939973c ch-remote: Address Rust 1.51.0 clippy issue (upper_case_acroynms)
warning: name `InvalidCPUCount` contains a capitalized acronym
  --> src/bin/ch-remote.rs:24:5
   |
24 |     InvalidCPUCount(std::num::ParseIntError),
   |     ^^^^^^^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `InvalidCpuCount`
   |
   = note: `#[warn(clippy::upper_case_acronyms)]` on by default
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
0c27f69f1c hypervisor: Address Rust 1.51.0 clippy issue (upper_case_acroynms)
warning: name `TranslateGVA` contains a capitalized acronym
  --> hypervisor/src/arch/emulator/mod.rs:51:5
   |
51 |     TranslateGVA(#[source] anyhow::Error),
   |     ^^^^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `TranslateGva`
   |
   = note: `#[warn(clippy::upper_case_acronyms)]` on by default
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
7d5d9bdcf4 vhost_user_block: Address Rust 1.51.0 clippy issue (redundant_slicing)
error: redundant slicing of the whole range
   --> vhost_user_block/src/lib.rs:396:31
    |
396 |         right.copy_from_slice(&data[..]);
    |                               ^^^^^^^^^ help: use the original slice instead: `data`
    |
    = note: `-D clippy::redundant-slicing` implied by `-D warnings`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
85ad72490f arch: Address Rust 1.51.0 clippy issue (upper_case_acronyms)
error: name `RSDPPastRamEnd` contains a capitalized acronym
  --> arch/src/lib.rs:59:5
   |
59 |     RSDPPastRamEnd,
   |     ^^^^^^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `RsdpPastRamEnd`
   |
   = note: `-D clippy::upper-case-acronyms` implied by `-D warnings`
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
80e48b545d block_util: Address Rust 1.51.0 clippy issue (ptr-arg)
error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.
  --> block_util/src/lib.rs:68:31
   |
68 | fn build_device_id(disk_path: &PathBuf) -> result::Result<String, Error> {
   |                               ^^^^^^^^ help: change this to: `&Path`
   |
   = note: `-D clippy::ptr-arg` implied by `-D warnings`
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg

error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.
  --> block_util/src/lib.rs:83:39
   |
83 | pub fn build_disk_image_id(disk_path: &PathBuf) -> Vec<u8> {
   |                                       ^^^^^^^^ help: change this to: `&Path`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg

error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.
  --> block_util/src/lib.rs:68:31
   |
68 | fn build_device_id(disk_path: &PathBuf) -> result::Result<String, Error> {
   |                               ^^^^^^^^ help: change this to: `&Path`
   |
   = note: `-D clippy::ptr-arg` implied by `-D warnings`
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg

error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.
  --> block_util/src/lib.rs:83:39
   |
83 | pub fn build_disk_image_id(disk_path: &PathBuf) -> Vec<u8> {
   |                                       ^^^^^^^^ help: change this to: `&Path`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
eb18ea61f4 net_util: Address Rust 1.51.0 clippy issue (redundant_slicing)
error: redundant slicing of the whole range
  --> net_util/src/mac.rs:60:35
   |
60 |         bytes[..].copy_from_slice(&src[..]);
   |                                   ^^^^^^^^ help: use the original slice instead: `src`
   |
   = note: `-D clippy::redundant-slicing` implied by `-D warnings`
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
bfbd75b2cf qcow: Address Rust 1.51.0 clippy issue (redundant-semicolons)
error: unnecessary trailing semicolon
    --> qcow/src/qcow.rs:2050:14
     |
2050 |             };
     |              ^ help: remove this semicolon
     |
     = note: `-D redundant-semicolons` implied by `-D warnings`

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
6dc3d60b2d block_util: Address Rust 1.51.0 clippy issue (upper_case_acronyms)
error: name `TYPE_UNKNOWN` contains a capitalized acronym
  --> vm-virtio/src/lib.rs:48:5
   |
48 |     TYPE_UNKNOWN = 0xFF,
   |     ^^^^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `Type_Unknown`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms

error: name `GetDeviceID` contains a capitalized acronym
   --> block_util/src/lib.rs:138:5
    |
138 |     GetDeviceID,
    |     ^^^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `GetDeviceId`
    |
    = note: `-D clippy::upper-case-acronyms` implied by `-D warnings`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
aa34d545f6 vm-virtio, virtio-devices: Address Rust 1.51.0 clippy issue (upper_case_acronyms)
error: name `TYPE_UNKNOWN` contains a capitalized acronym
  --> vm-virtio/src/lib.rs:48:5
   |
48 |     TYPE_UNKNOWN = 0xFF,
   |     ^^^^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `Type_Unknown`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
261c039831 acpi_tables: Address Rust 1.51.0 clippy issue (vec_init_then_push)
error: calls to `push` immediately after creation
    --> acpi_tables/src/aml.rs:1194:9
     |
1194 | /         let mut bytes = Vec::new();
1195 | |         bytes.push(0x8a); /* CreateDWordFieldOp */
     | |_________________________^ help: consider using the `vec![]` macro: `let mut bytes = vec![..];`
     |
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#vec_init_then_push

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
db6516931d acpi_tables: Address Rust 1.51.0 clippy issue (upper_case_acronyms)
error: name `SDT` contains a capitalized acronym
  --> acpi_tables/src/sdt.rs:27:12
   |
27 | pub struct SDT {
   |            ^^^ help: consider making the acronym lowercase, except the initial letter: `Sdt`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
030d6046b2 api_client: Address Rust 1.51.0 clippy issue (upper_case_acroynms)
--> api_client/src/lib.rs:40:5
   |
40 |     OK,
   |     ^^ help: consider making the acronym lowercase, except the initial letter (notice the capitalization): `Ok`
   |
   = note: `-D clippy::upper-case-acronyms` implied by `-D warnings`
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-26 11:32:09 +00:00
Rob Bradford
7390475636 arch: Report use of deprecated LinuxBoot protocol
With CONFIG_PVH in stable kernels for some time we should deprecate the
use of alternative boot methods since this will lead to a much simpler
boot flow and CI process.

See: #2231

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-25 13:59:19 +00:00
Rob Bradford
c4564f3ba8 block_util: Enhance error reporting for virtio-block usage
There are multiple reports of DescriptorChainTooShort errors and so add
some extra debugging to aid the debugging of this issue.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-25 13:41:54 +01:00
Wei Liu
27ba8133a4 vmm: interrupt: drop RoutingEntryExt trait
We can now directly use associated functions.

This simplifies code and causes no functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-03-25 10:13:43 +01:00
Wei Liu
f5c550affb vmm: interrupt: simplify interrupt handling traits
Drop the generic type E and use IrqRoutngEntry directly. This allows
dropping a bunch of trait bounds from code.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-03-25 10:13:43 +01:00
Wei Liu
1d9f27c9fb vmm: interrupt: extract common code from MSHV and KVM
Their make_entry functions look the same now. Extract the logic to a
common function.

No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-03-25 10:13:43 +01:00
Rob Bradford
8b7aafad16 virtio-devices: block: Remove unused members of Error enum
These are residual enum members from a previous refactoring.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-24 17:27:41 +01:00
Rob Bradford
46d082763f vm-virtio: queue: Fix comment for DescriptorChain::has_next()
This returns trues if this descriptor has another descriptor linked to
it. Not whether this descriptor chain has another one following it.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-24 17:26:53 +01:00
Rob Bradford
6170ba06d1 README.md: Update URL for hypervisor-fw
The 0.3.0 release (re)supports booting stock Ubuntu images so users
should be pointed towards that.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-24 11:41:13 +01:00
Sebastien Boeuf
63304d0be7 net_util: Check descriptor size
There is no point in queueing an empty descriptor in the list of iovecs.
Let's simply ignore such case and avoid some unnecessary processing.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-24 11:41:05 +01:00
Sebastien Boeuf
1cd186c83c docs: Update hotplug documentation with ch-remote
Replacing old instructions using curl with ch-remote ones.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-23 14:55:49 -07:00
Sebastien Boeuf
5581486149 docs: Expand memory hotplug documentation for virtio-mem
The hotplug documentation was missing the explanation on how to use
memory hotplug with virtio-mem.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-23 14:55:49 -07:00
Sebastien Boeuf
3e3c163285 docs: Extend documentation with PCI device hotplug
Add explanations about PCI device hotplug along with CPU and memory
hotplug.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-23 14:55:49 -07:00
Sebastien Boeuf
6190e64f2f docs: Add seccomp documentation
Document that seccomp is on and how to disable it along with a pointer
on how to identify missing syscalls during development.

Fixes #993

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-23 18:41:30 +01:00
Rob Bradford
88c30764e0 tests: Move test_infra from a module to crate
It must be specified as excluded from the workspace as it must not be
built on non-test targets due to issues with the ssh2 dependency and the
musl toolchain.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-23 18:04:50 +01:00
dependabot-preview[bot]
91145afa9b build(deps): bump serde from 1.0.124 to 1.0.125 in /fuzz
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.124 to 1.0.125.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.124...v1.0.125)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-23 11:52:04 +00:00
dependabot-preview[bot]
50d57b2b6f build(deps): bump serde_derive from 1.0.124 to 1.0.125 in /fuzz
Bumps [serde_derive](https://github.com/serde-rs/serde) from 1.0.124 to 1.0.125.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.124...v1.0.125)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-23 11:15:32 +00:00
Vineeth Pillai
68401e6e4a hypervisor:mshv: Support the move of MSI routing to kernel
Signed-off-by: Vineeth Pillai <viremana@linux.microsoft.com>
2021-03-23 11:06:13 +01:00
Vineeth Pillai
7fad74cb04 hypervisor: refactor vec_with_array_field function
refactor vec_with_array_field to common hypervisor code
so that mshv can also make use of it.

Signed-off-by: Vineeth Pillai <viremana@linux.microsoft.com>
2021-03-23 11:06:13 +01:00
dependabot-preview[bot]
b8c0cd5cd4 build(deps): bump serde_derive from 1.0.124 to 1.0.125
Bumps [serde_derive](https://github.com/serde-rs/serde) from 1.0.124 to 1.0.125.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.124...v1.0.125)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-23 08:10:45 +00:00
dependabot-preview[bot]
874ffe60ca build(deps): bump serde from 1.0.124 to 1.0.125
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.124 to 1.0.125.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.124...v1.0.125)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-23 07:28:35 +00:00
dependabot-preview[bot]
e9793020c2 build(deps): bump libc from 0.2.90 to 0.2.91
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.90 to 0.2.91.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.90...0.2.91)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-23 06:56:04 +00:00
Sebastien Boeuf
d370ea585b deps: bump iced-x86 from 1.10.3 to 1.11.0
Bumps iced-x86 from 1.10.3 to 1.11.0.

Manual update of the code was needed since memory_displacement() was
deprecated and replaced with either memory_displacement32() or
memory_displacement64().

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-22 15:17:09 +00:00
Sebastien Boeuf
1e11e6789a vmm: device_manager: Factorize passthrough_device creation
There's no need to have the code creating the passthrough_device being
duplicated since we can factorize it in a function used in both cases
(both cold plugged and hot plugged devices VFIO devices).

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-22 10:47:33 +01:00
dependabot-preview[bot]
f6da2bb5e1 build(deps): bump anyhow from 1.0.38 to 1.0.39 in /fuzz
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.38 to 1.0.39.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.38...1.0.39)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-22 07:47:26 +00:00
dependabot-preview[bot]
987e52090f build(deps): bump anyhow from 1.0.38 to 1.0.39
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.38 to 1.0.39.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.38...1.0.39)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-20 08:05:06 +00:00
dependabot-preview[bot]
195ac4c5dc build(deps): bump vhost from ee3e872 to 05cd8b2
Bumps [vhost](https://github.com/rust-vmm/vhost) from `ee3e872` to `05cd8b2`.
- [Release notes](https://github.com/rust-vmm/vhost/releases)
- [Commits](ee3e872270...05cd8b2ad3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-19 07:52:46 +00:00
dependabot-preview[bot]
685a1760f3 build(deps): bump libc from 0.2.89 to 0.2.90 in /fuzz
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.89 to 0.2.90.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.89...0.2.90)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-19 07:52:32 +00:00
dependabot-preview[bot]
e39924d45a build(deps): bump libc from 0.2.89 to 0.2.90
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.89 to 0.2.90.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.89...0.2.90)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-18 21:29:25 +00:00
Sebastien Boeuf
b06fd80fa9 vmm: device_manager: Use DeviceTree to store PCI devices
Extend and use the existing DeviceTree to retrieve useful information
related to PCI devices. This removes the duplication with pci_devices
field which was internal to the DeviceManager.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-18 15:26:25 +01:00
Sebastien Boeuf
c8c3cad8cb vmm: device_manager: Update structure holding PCI IRQs
Make the code a bit clearer by changing the naming of the structure
holding the list of IRQs reserved for PCI devices. It is also modified
into an array of 32 entries since we know this is the amount of PCI
slots that is supported.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-18 15:26:25 +01:00
Sebastien Boeuf
e311fd66cd vmm: device_manager: Remove the need for Any
We define a new enum in order to classify PCI device under virtio or
VFIO. This is a cleaner approach than using the Any trait, and
downcasting it to find the object back.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-18 15:26:25 +01:00
Sebastien Boeuf
fbd624d816 vmm: device_manager: Remove pci_id_list
Introduces a tuple holding both information needed by pci_id_list and
pci_devices.

Changes pci_devices to be a BTreeMap of this new tuple.

Now that pci_devices holds the information needed from pci_id_list,
pci_id_list is no longer needed.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-18 15:26:25 +01:00
Sebastien Boeuf
305e095d15 vmm: device_manager: Invert pci_id_list HashMap
In anticipation for further factorization, the pci_id_list is now a
hashmap of PCI b/d/f leading to each device name.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-18 15:26:25 +01:00
Sebastien Boeuf
62aaccee28 vmm: Device name verification based on DeviceTree
Instead of relying on a PCI specific device list, we use the DeviceTree
as a reference to determine if a device name is already in use or not.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-18 15:26:25 +01:00
Rob Bradford
13724dbd22 main: Remove messages from startup
Remove the startup message containing incomplete VM configuration
details. It's a bit unusual for a tool such as Cloud Hypervisor to print
those kind of details which are a direct representation of the command
line.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-18 11:32:28 +00:00
Rob Bradford
16cb40733a tests: Extract out generic integration test code
This includes:

* OS disk image management
* Cloud init creation
* SSH to guest access
* Waiting for guest to boot

This will be useful in other projects that want to do similar things in
their integration tests.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-17 12:18:04 +00:00
Rob Bradford
9440304183 vmm: http: Error out earlier if we can't create API server
This removes a panic inside the API thread.

Fixes: #2395

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-17 11:30:26 +00:00
Rob Bradford
78f9ddc6be main: Remove default API sever path
Only create an API server if the use specifies one with `--api-socket`

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-17 11:30:26 +00:00
Rob Bradford
9b0996a71f vmm, main: Optionalise creation of API server
Only if we have a valid API server path then create the API server. For
now this has no functional change there is a default API server path in
the clap handling but rather prepares to do so optionally.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-17 11:30:26 +00:00
Zide Chen
f685f0e0b2 vm-virtio: initialize MSI-X vectors with VIRTIO_MSI_NO_VECTOR
In case of the virtio frontend driver doesn't need interupts for
certain queue event, it may explicitly write VIRTIO_MSI_NO_VECTOR
to the virtio common configuration, or it may doesn't configure
the event type vector at all.

This patch initializes both MSI-X configuration vector and queue vector
with VIRTIO_MSI_NO_VECTOR, so that the backend drivers won't trigger
unexpected interrupts to the guest.

Signed-off-by: Zide Chen <zide.chen@intel.com>
2021-03-17 08:05:24 +01:00
dependabot-preview[bot]
40a3c31df4 build(deps): bump vfio-ioctls from a87b13b to ed8d253
Bumps [vfio-ioctls](https://github.com/rust-vmm/vfio-ioctls) from `a87b13b` to `ed8d253`.
- [Release notes](https://github.com/rust-vmm/vfio-ioctls/releases)
- [Commits](a87b13bdec...ed8d253457)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-17 07:58:11 +01:00
Sebastien Boeuf
04dc496808 ci: Enable baremetal VFIO integration tests
Relying on a NVIDIA Tesla T4 card present in the SGX machine, this patch
enables baremetal VFIO testing, validated by running several NVIDIA
tools in the guest. The guest image has been prepared to include all the
software needed to run these tests.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-16 18:59:46 +00:00
Henry Wang
d0c0a98eda docs: Update the device model documentation
This commit updates the device model documentation with Arm
specific devices.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-03-16 20:27:15 +08:00
Henry Wang
205e587fad tests: Enable test_power_button for AArch64
This commit enables the test_power_button test case for AArch64.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-03-16 20:27:15 +08:00
Henry Wang
2bb153de2b vmm: Implement the power button method for AArch64
This commit implements the power button method for AArch64 using
the PL061 GPIO controller.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-03-16 20:27:15 +08:00
Henry Wang
c853ed3fdc resources: Enable GPIO PL061 driver in kernel
This commit enables the kernel config of PL061 GPIO controller.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-03-16 20:27:15 +08:00
Henry Wang
a59ff42a95 aarch64: Add PL061 for device tree implementation
This commit adds a new legacy device PL011 for the AArch64 device
tree implementation.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-03-16 20:27:15 +08:00
Penny Zheng
7c86ef8a69 devices: legacy: Add Arm PL061 GPIO controller
This commit implements ARM PrimeCell General Purpose Input/Output
(GPIO) PL061 device specification.

Signed-off-by: Penny Zheng <penny.zheng@arm.com>
Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-03-16 20:27:15 +08:00
dependabot-preview[bot]
c7438c8b22 build(deps): bump libc from 0.2.88 to 0.2.89 in /fuzz
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.88 to 0.2.89.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.88...0.2.89)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-16 08:13:22 +00:00
dependabot-preview[bot]
3df2e2629b build(deps): bump io-uring from 0.5.0 to 0.5.1 in /fuzz
Bumps [io-uring](https://github.com/tokio-rs/io-uring) from 0.5.0 to 0.5.1.
- [Release notes](https://github.com/tokio-rs/io-uring/releases)
- [Commits](https://github.com/tokio-rs/io-uring/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-16 08:13:10 +00:00
Henry Wang
06d83d2eb3 docs: device_model: Updated the serial device doc
As we switched the AArch64 serial device to PL011, we also need to
update the documentation.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-03-16 11:53:51 +08:00
Henry Wang
9c3b489f0e tests: Switch AArch64 serial test cases to ttyAMA0
This commit switches the serial test cases for AArch64 to ttyAMA0.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-03-16 11:53:51 +08:00
Henry Wang
3965a8505b resources: AArch64: Enable PL011 driver in kernel
This commit enables the kernel config of PL011 UART controller.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-03-16 11:53:51 +08:00
Henry Wang
a8cde12b14 vmm: AArch64: Use PL011 for AArch64 device tree
This commit switches the default serial device from 16550 to the
Arm dedicated UART controller PL011. The `ttyAMA0` can be enabled.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-03-16 11:53:51 +08:00
Henry Wang
fd95acc60f devices: legacy: Implement Arm PL011 UART
This commit implements the Arm PrimeCell UART(PL011) device.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-03-16 11:53:51 +08:00
dependabot-preview[bot]
c85fba0c43 build(deps): bump libc from 0.2.88 to 0.2.89
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.88 to 0.2.89.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.88...0.2.89)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-15 23:40:01 +00:00
Iggy Jackson
fea1f370ff docs: Add virtiofs root howto
Add a quick HowTo for using a virtiofs root filesystem in a
cloud-hypervisor guest.

Signed-off-by: Iggy Jackson <iggy@theiggy.com>
2021-03-16 00:10:49 +01:00
Bo Chen
6307db5699 virtio-devices: seccomp: Add 'timerfd_settime' to block device
The `timerfd_settime` syscall is required when I/O throttling is
enabled.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-03-15 20:19:33 +00:00
dependabot-preview[bot]
548426c128 build(deps): bump io-uring from 0.5.0 to 0.5.1
Bumps [io-uring](https://github.com/tokio-rs/io-uring) from 0.5.0 to 0.5.1.
- [Release notes](https://github.com/tokio-rs/io-uring/releases)
- [Commits](https://github.com/tokio-rs/io-uring/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-15 17:51:01 +00:00
Michael Zhao
c3a75dafc5 tests: Enable serial test cases for AArch64
Enabled all "ttyS0" related test cases:
- test_serial_off
- test_serial_tty
- test_serial_file

Enabled mandatory guest kernel driver for "ns16550a" on AArch64.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-03-15 20:59:50 +08:00
Michael Zhao
ee7fcdb3cf aarch64: Correct wrong settings for serial device
Corrected:
- The device name in FDT
- MMIO mapping size

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-03-15 20:59:50 +08:00
Michael Zhao
afc83582be aarch64: Enable IRQ routing for legacy devices
On AArch64, interrupt controller (GIC) is emulated by KVM. VMM need to
set IRQ routing for devices, including legacy ones.

Before this commit, IRQ routing was only set for MSI. Legacy routing
entries of type KVM_IRQ_ROUTING_IRQCHIP were missing. That is way legacy
devices (like serial device ttyS0) does not work.

The setting of X86 IRQ routing entries are not impacted.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-03-15 20:59:50 +08:00
dependabot-preview[bot]
2a8bdf710d build(deps): bump syn from 1.0.63 to 1.0.64 in /fuzz
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.63 to 1.0.64.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.63...1.0.64)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-15 08:35:57 +00:00
dependabot-preview[bot]
210a9d40c8 build(deps): bump regex from 1.4.4 to 1.4.5
Bumps [regex](https://github.com/rust-lang/regex) from 1.4.4 to 1.4.5.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.4.4...1.4.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-14 22:03:20 +00:00
dependabot-preview[bot]
5bb10adf22 build(deps): bump syn from 1.0.63 to 1.0.64
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.63 to 1.0.64.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.63...1.0.64)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-14 22:03:04 +00:00
dependabot-preview[bot]
97f8f0fb31 build(deps): bump openssl-sys from 0.9.60 to 0.9.61
Bumps [openssl-sys](https://github.com/sfackler/rust-openssl) from 0.9.60 to 0.9.61.
- [Release notes](https://github.com/sfackler/rust-openssl/releases)
- [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.60...openssl-sys-v0.9.61)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-14 22:02:49 +00:00
Rob Bradford
5bc311184e build: Remove url crate dependency
This removes multiple transitive dependencies and speeds up our build.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-12 16:52:55 +01:00
Rob Bradford
7f96eb2b67 vmm: migration: Simplify url socket handling in migration code
Extract URL handling to a common function and simplify to remove url
crate dependency.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-12 16:52:55 +01:00
Rob Bradford
ab4b30edd3 vmm: Switch MemoryManager::send() to url_to_path()
This continues the work in cc78a597cd

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-12 16:52:55 +01:00
Rob Bradford
cc78a597cd vmm: Simplify snapshot/restore path handling
Extend the existing url_to_path() to take the URL string and then use
that to simplify the snapshot/restore code paths.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-12 13:03:01 +01:00
Bo Chen
ebcbab739e vmm: openapi: Add rate_limiter_config to the `DiskConfig
Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-03-12 09:35:03 +01:00
Bo Chen
0c7541473c docs: Add documentation on I/O throttling
Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-03-12 09:35:03 +01:00
Bo Chen
169d6f6756 fuzz: Update the 'block' fuzz target with the rate limiter support
Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-03-12 09:35:03 +01:00
Bo Chen
af8def364d virtio-devices, vmm: add I/O rate limiter on block device
This patch is based on the 'rate_limiter' module from firecracker[1]. To
simplify dependencies, we reply on 'vmm-sys-util::TimerFd' instead of
the `timerfd` crate.

[1]https://github.com/firecracker-microvm/firecracker/tree/master/src/rate_limiter

Fixes: #1285

Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-03-12 09:35:03 +01:00
dependabot-preview[bot]
c45a9a390d build(deps): bump regex from 1.4.3 to 1.4.4
Bumps [regex](https://github.com/rust-lang/regex) from 1.4.3 to 1.4.4.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.4.3...1.4.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-12 08:33:23 +00:00
dependabot-preview[bot]
b5929645c6 build(deps): bump regex-syntax from 0.6.22 to 0.6.23
Bumps [regex-syntax](https://github.com/rust-lang/regex) from 0.6.22 to 0.6.23.
- [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)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-12 08:33:05 +00:00
Sebastien Boeuf
ec9e6edcd0 virtio-devices: Remove unused update_memory() from VirtioDevice trait
Now that virtio devices can be updated with add_memory_region(), there's
no need to keep update_memory() around.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-11 19:04:21 +01:00
Sebastien Boeuf
00873e5f84 vmm: device_manager: Update virtio devices memory with a single region
Relies on the preliminary work allowing virtio devices to be updated
with a single memory at a time instead of updating the entire memory at
once.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-11 19:04:21 +01:00
Sebastien Boeuf
9e53efa3ca virtio-devices: Add support for adding a single memory region
Assuming vhost-user devices support CONFIGURE_MEM_SLOTS protocol
feature, we introduce a new method to the VirtioDevice trait in order to
update one single memory at a time.

In case CONFIGURE_MEM_SLOTS is not supported by the backend (feature not
acked), we fallback onto the current way of updating the memory
mappings, that is with SET_MEM_TABLE.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-11 19:04:21 +01:00
Sebastien Boeuf
4f22f57651 vhost_user_net: Enable CONFIGURE_MEM_SLOTS protocol feature
In order to support GET_MAX_MEM_SLOTS, ADD_MEM_REG and REM_MEM_REG, the
protocol feature CONFIGURE_MEM_SLOTS must be enabled.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-11 19:04:21 +01:00
Sebastien Boeuf
1e1cbc53c1 vhost_user_blk: Enable CONFIGURE_MEM_SLOTS protocol feature
In order to support GET_MAX_MEM_SLOTS, ADD_MEM_REG and REM_MEM_REG, the
protocol feature CONFIGURE_MEM_SLOTS must be enabled.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-11 19:04:21 +01:00
Sebastien Boeuf
8255d5f774 vhost_user_backend: Move to latest vhost version
The latest vhost version adds the support for the new commands
get_max_mem_slots(), add_mem_region() and remove_mem_region(), all
related to the new vhost-user protocol feature CONFIGURE_MEM_SLOTS.

The vhost_user_backend crate is updated accordingly in order to support
these new commands, mostly related to the capability of updating the
guest memory mappings with a finer control than set_mem_table() command.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-11 19:04:21 +01:00
Sebastien Boeuf
e3a8d6c13c virtio-devices: vhost-user: net: Fix seccomp filters
On x86_64 architecture, multiple syscalls were missing when shutting
down the vhost-user-net device along with the VM. This was causing the
usual crash related to seccomp filters.

This commit adds these missing syscalls to fix the issue.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-11 19:04:21 +01:00
Sebastien Boeuf
581bf4aad5 virtio-devices: vhost-user: Fix device reset
There is no need to get the vring base when resetting the vhost-user
device. This was mostly ignored, but in some cases, it was causing some
actual errors.

A reset must simply be a combination of disabling the vrings along with
the reset of the owner.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-11 19:04:21 +01:00
Jiachen Zhang
16b82f3dfe vhost-user: Make ActivateError messages more consistent
Originally, VhostUserSetup is only used by vhost-user-fs. While
vhost-user-blk and vhost-user-net have their own error messages,
we rename VhostUserSetup to VhostUserFsSetup.

Signed-off-by: Jiachen Zhang <zhangjiachen.jaycee@bytedance.com>
2021-03-11 15:09:07 +00:00
dependabot-preview[bot]
675a8f808c build(deps): bump signal-hook from 0.3.6 to 0.3.7 in /fuzz
Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.3.6 to 0.3.7.
- [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/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-11 09:29:26 +00:00
dependabot-preview[bot]
59e5048436 build(deps): bump byteorder from 1.4.2 to 1.4.3 in /fuzz
Bumps [byteorder](https://github.com/BurntSushi/byteorder) from 1.4.2 to 1.4.3.
- [Release notes](https://github.com/BurntSushi/byteorder/releases)
- [Changelog](https://github.com/BurntSushi/byteorder/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/byteorder/compare/1.4.2...1.4.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-11 08:45:59 +00:00
dependabot-preview[bot]
7b3e79cdfa build(deps): bump signal-hook from 0.3.6 to 0.3.7
Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.3.6 to 0.3.7.
- [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/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-11 08:45:27 +00:00
Rob Bradford
66ffaceffc vmm: tdx: Correctly populate the 64-bit MMIO region
The MMIO structure contains the length rather than the maximum address
so it is necessary to subtract the starting address from the end address
to calculate the length.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-10 14:45:51 +00:00
dependabot-preview[bot]
4e307788b7 build(deps): bump byteorder from 1.4.2 to 1.4.3
Bumps [byteorder](https://github.com/BurntSushi/byteorder) from 1.4.2 to 1.4.3.
- [Release notes](https://github.com/BurntSushi/byteorder/releases)
- [Changelog](https://github.com/BurntSushi/byteorder/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/byteorder/compare/1.4.2...1.4.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-10 13:14:58 +00:00
Muminul Islam
8739f6cccb scripts: Fix windows test script for running on MSHV
In order to run Windows test on MSHV we need to build and test using
MSHV feature.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2021-03-10 10:08:12 +00:00
dependabot-preview[bot]
5599cbef50 build(deps): bump syn from 1.0.62 to 1.0.63 in /fuzz
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.62 to 1.0.63.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.62...1.0.63)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-10 08:03:10 +00:00
dependabot-preview[bot]
4c52ad2550 build(deps): bump syn from 1.0.62 to 1.0.63
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.62 to 1.0.63.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.62...1.0.63)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-10 08:02:59 +00:00
Rob Bradford
a0c07474a3 vmm: seccomp: Add KVM_MEMORY_ENCRYPT_OP ioctl to seccomp filter
This is the basis for TDX based operations on the various KVM file
descriptors.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-09 16:26:06 +01:00
Rob Bradford
be0cbb09b1 build: Clippy check with "tdx" feature
In the absence of a way of integration testing this testing that it
compiles is reasonable compromise.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-08 18:30:00 +00:00
Rob Bradford
d24aa887b6 vmm: Reject VM snapshot request if TDX in use
It is not possible to snapshot the contents of a TDX VM.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-08 18:30:00 +00:00
Rob Bradford
835a31e283 vmm: config: Require max and boot vCPUs to be equal for TDX
CPU hotplug is not possible with TDX

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-08 18:30:00 +00:00
Rob Bradford
57c8c250fd tdx: Permit starting Cloud Hypervisor without --kernel
This is not required if TDX is present.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-08 18:30:00 +00:00
Rob Bradford
62abc117ab tdx: Configure TDX state for the VM
Load the sections backed from the file into their required addresses in
memory and populate the HOB with details of the memory. Using the HOB
address initialize the TDX state in the vCPUs and finalize the TDX
configuration.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-08 18:30:00 +00:00
Rob Bradford
1c54fc3ab7 hypervisor: Support creating a VM of a specified KVM type
This is necessary to support creating a TD VM.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-08 18:30:00 +00:00
Rob Bradford
57ce0986f7 vmm: cpu: Add functionality for enabling TDX for all vCPUs
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-08 18:30:00 +00:00
Rob Bradford
c8cad394b5 vmm: cpu: Expose the common/shared CPUID data for all vCPUs
This allows the CPUID data to be passed into the VM level ioctl used for
initalizing TDX.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-08 18:30:00 +00:00
Rob Bradford
b02aff5761 vmm: memory_manager: Disable dirty page logging when running on TDX
It is not permitted to have this enabled in memory that is part of a TD.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-08 18:30:00 +00:00
Rob Bradford
f282cc001a tdx: Add abstraction to call TDX ioctls to hypervisor
Add API to the hypervisor interface and implement for KVM to allow the
special TDX KVM ioctls on the VM and vCPU FDs.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-08 18:30:00 +00:00
Rob Bradford
c48e82915d vmm: Make kernel optional in VM internals
When booting with TDX no kernel is supplied as the TDFV is responsible
for loading the OS. The requirement to have the kernel is still
currently enforced at the validation entry point; this change merely
changes function prototypes and stored state to use Option<> to support.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-08 18:30:00 +00:00
Rob Bradford
66a3bed086 vmm: config: Add "--tdx" option parsing
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-08 18:30:00 +00:00
Rob Bradford
45cc26f940 tdx: Add support for generating a TD HOB list
This is used to communicate details of the memory configuration from the
VMM into the TDMF.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-08 18:30:00 +00:00
Rob Bradford
77955bd8f9 tdx: Add support for parsing TDVF metadata
Add support extracting the sections out for a TDVF file which can be
then used to load the TDVF and TD HOB data into their appropriate
locations.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-08 18:30:00 +00:00
Rob Bradford
e61ee6bcac tdx: Add "tdx" feature with an empty module inside arch to implement
Add the skeleton of the "tdx" feature with a module ready inside the
arch crate to store implementation details.

TEST=cargo build --features="tdx"

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-08 18:30:00 +00:00
Vineeth Pillai
fd9bd1c86c main: minor fix in the help message for event monitor
Signed-off-by: Vineeth Pillai <viremana@linux.microsoft.com>
2021-03-08 15:32:18 +00:00
Rob Bradford
cf9e81c05a build: Update kvm-ioctls and kvm-bindings dependencies
These need to be updated together as the kvm-ioctls depends upon a
strictly newer version of kvm-bindings which requires a rebase in the CH
fork.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-08 14:52:30 +00:00
dependabot-preview[bot]
a4a2d6fbee build(deps): bump syn from 1.0.61 to 1.0.62 in /fuzz
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.61 to 1.0.62.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.61...1.0.62)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-08 08:56:23 +00:00
dependabot-preview[bot]
94083793a6 build(deps): bump serde from 1.0.123 to 1.0.124 in /fuzz
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.123 to 1.0.124.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.123...v1.0.124)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-08 08:46:07 +00:00
dependabot-preview[bot]
8ae966e975 build(deps): bump syn from 1.0.61 to 1.0.62
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.61 to 1.0.62.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.61...1.0.62)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-08 07:46:17 +00:00
dependabot-preview[bot]
f68fe54b9b build(deps): bump vhost from 62fd4ec to 7784304
Bumps [vhost](https://github.com/rust-vmm/vhost) from `62fd4ec` to `7784304`.
- [Release notes](https://github.com/rust-vmm/vhost/releases)
- [Commits](62fd4ec5a4...7784304860)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-08 07:45:52 +00:00
dependabot-preview[bot]
54e1796da6 build(deps): bump serde from 1.0.123 to 1.0.124
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.123 to 1.0.124.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.123...v1.0.124)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-07 23:09:32 +00:00
dependabot-preview[bot]
c8be08adf6 build(deps): bump serde_derive from 1.0.123 to 1.0.124
Bumps [serde_derive](https://github.com/serde-rs/serde) from 1.0.123 to 1.0.124.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.123...v1.0.124)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-07 21:54:56 +00:00
dependabot-preview[bot]
ccfa34d066 build(deps): bump libc from 0.2.87 to 0.2.88
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.87 to 0.2.88.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.87...0.2.88)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-05 18:39:37 +00:00
Sebastien Boeuf
d65a0b68b9 Revert "Jenkinsfile: Temporarily disable SGX CI"
This reverts commit 526cf32a78.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-05 19:02:30 +01:00
William Douglas
56028fb214 Try to restore pty configuration on reboot
When a vm is created with a pty device, on reboot the pty fd (sub
only) will only be associated with the vmm through the epoll event
loop. The fd being polled will have been closed due to the vm itself
dropping the pty files (and potentially reopening the fd index to a
different item making things quite confusing) and new pty fds will be
opened but not polled on for input.

This change creates a structure to encapsulate the information about
the pty fd (main File, sub File and the path to the sub File). On
reboot, a copy of the console and serial pty structs is then passed
down to the new Vm  instance which will be used instead of creating a
new pty device.

This resolves the underlying issue from #2316.

Signed-off-by: William Douglas <william.r.douglas@gmail.com>
2021-03-05 18:34:52 +01:00
Sebastien Boeuf
933d41cf2f vmm: Provide DMA mapping handlers to virtio-mem devices
Now that virtio-mem devices can update VFIO mappings through dedicated
handlers, let's provide them from the DeviceManager.

Important to note these handlers should either be provided to virtio-mem
devices or to the unique virtio-iommu device. This must be mutually
exclusive.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-05 10:38:42 +01:00
Sebastien Boeuf
61f9a4ec6c virtio-devices: mem: Accept handlers to update DMA mappings
Create two functions for registering/unregistering DMA mapping handlers,
each handler being associated with a VFIO device.

Whenever the plugged_size is modified (which means triggered by the
virtio-mem driver in the guest), the virtio-mem backend is responsible
for updating the DMA mappings related to every VFIO device through the
handler previously provided.

It's important to update the map when the handler is either registered
or unregistered as well, as we don't want to miss some plugged memory
that would have been added before the VFIO device is added to the VM.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-05 10:38:42 +01:00
Sebastien Boeuf
080ea31813 pci, vmm: Manage VFIO DMA mapping from DeviceManager
Instead of letting the VfioPciDevice take the decision on how/when to
perform the DMA mapping/unmapping, we move this to the DeviceManager
instead.

The point is to let the DeviceManager choose which guest memory regions
should be mapped or not. In particular, we don't want the virtio-mem
region to be mapped/unmapped as it will be virtio-mem device
responsibility to do so.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-05 10:38:42 +01:00
Sebastien Boeuf
d6db2fdf96 vmm: memory_manager: Add ACPI hotplug region to default memory zone
When memory is resized through ACPI, a new region is added to the guest
memory. This region must also be added to the corresponding memory zone
in order to keep everything in sync.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-05 10:38:42 +01:00
dependabot-preview[bot]
f1aa09f178 build(deps): bump syn from 1.0.60 to 1.0.61 in /fuzz
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.60 to 1.0.61.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.60...1.0.61)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-05 07:49:52 +00:00
dependabot-preview[bot]
8cbb7b15a9 build(deps): bump syn from 1.0.60 to 1.0.61
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.60 to 1.0.61.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.60...1.0.61)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-05 07:14:58 +00:00
Rob Bradford
b65502c3c1 main: Refine event monitor control
Replace "--monitor-fd" with "--event-monitor" which can either take
"fd=<int>" or "path=<path>" which can point to e.g. a named pipe and
allow more flexibility.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-04 19:12:40 +01:00
dependabot-preview[bot]
3ef7c8eac5 build(deps): bump vhost from 576694b to 62fd4ec
Bumps [vhost](https://github.com/rust-vmm/vhost) from `576694b` to `62fd4ec`.
- [Release notes](https://github.com/rust-vmm/vhost/releases)
- [Commits](576694bcfb...62fd4ec5a4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-04 08:38:19 +00:00
Sebastien Boeuf
526cf32a78 Jenkinsfile: Temporarily disable SGX CI
Since the SGX server is down for maintenance, all builds are waiting on
the node agent to answer, causing all PRs to be blocked.

Let's disable temporarily the SGX CI until the server is back up.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-03 09:56:05 +00:00
dependabot-preview[bot]
b0ddc5bd60 build(deps): bump libc from 0.2.86 to 0.2.87 in /fuzz
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.86 to 0.2.87.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.86...0.2.87)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-03 10:21:43 +01:00
dependabot-preview[bot]
b72f6046e5 build(deps): bump vfio-ioctls from 0903c22 to a87b13b
Bumps [vfio-ioctls](https://github.com/rust-vmm/vfio-ioctls) from `0903c22` to `a87b13b`.
- [Release notes](https://github.com/rust-vmm/vfio-ioctls/releases)
- [Commits](0903c222fa...a87b13bdec)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-03 10:21:17 +01:00
dependabot-preview[bot]
8a2bd01e25 build(deps): bump once_cell from 1.7.1 to 1.7.2
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.7.1 to 1.7.2.
- [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.7.1...v1.7.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-02 15:53:53 +00:00
dependabot-preview[bot]
d433ae1656 build(deps): bump libc from 0.2.86 to 0.2.87
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.86 to 0.2.87.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.86...0.2.87)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-02 11:14:57 +00:00
dependabot-preview[bot]
0348f480fa build(deps): bump once_cell from 1.7.0 to 1.7.1
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.7.0 to 1.7.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.7.0...v1.7.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-02 09:24:39 +00:00
Wei Liu
74565538ae hypervisor: mshv: hook up TranslateGVA hypercall
At this stage this is the bare minimum needed to make Windows server
2019 work on MSHV.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-03-02 07:08:36 +01:00
Rob Bradford
99baee8d37 tests: Move Windows integration test to updated OVMF
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-03-01 22:11:19 +00:00
Wei Liu
030a86db17 hypervisor: mshv: simplify GVA to GPA cache
So far we've only had the need to emulate one instruction. There is no
need to use a HashMap when a simple tuple for the initial mapping will
do.

We can bring back the HashMap once more sophisticated use cases surface.

No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-03-01 17:50:47 +00:00
Wei Liu
3eb5b67dc3 hypervisor: mshv: make SoftTLB part of MshvEmulatorContext
This avoids code complexity down the line when we get around
implementing Windows support.

No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-03-01 17:50:47 +00:00
Sebastien Boeuf
c27d6df233 vhost: Bump to latest version from upstream
Moving to the latest version of the rust-vmm/vhost crate, before it gets
published on crates.io.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-01 15:53:46 +01:00
dependabot-preview[bot]
30cd3cb764 deps: bump io-uring from 0.4.0 to 0.5.0
Bumps [io-uring](https://github.com/tokio-rs/io-uring) from 0.4.0 to 0.5.0.
- [Release notes](https://github.com/tokio-rs/io-uring/releases)
- [Commits](https://github.com/tokio-rs/io-uring/commits)

The API was changed, hence some changes were needed to keep the code
building and functional.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-03-01 11:08:25 +00:00
dependabot-preview[bot]
e31c2be60a build(deps): bump serde_json from 1.0.63 to 1.0.64
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.63 to 1.0.64.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.63...v1.0.64)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-28 18:35:17 +00:00
dependabot-preview[bot]
fb853a50b1 build(deps): bump serde_json from 1.0.62 to 1.0.63
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.62 to 1.0.63.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.62...v1.0.63)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-26 13:00:32 +00:00
dependabot-preview[bot]
8c38d9576c build(deps): bump adler from 1.0.1 to 1.0.2
Bumps [adler](https://github.com/jonas-schievink/adler) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/jonas-schievink/adler/releases)
- [Changelog](https://github.com/jonas-schievink/adler/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jonas-schievink/adler/compare/v1.0.1...v1.0.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-26 12:46:18 +00:00
dependabot-preview[bot]
5e98810c2d build(deps): bump libfuzzer-sys from 0.3.5 to 0.4.0 in /fuzz
Bumps [libfuzzer-sys](https://github.com/rust-fuzz/libfuzzer) from 0.3.5 to 0.4.0.
- [Release notes](https://github.com/rust-fuzz/libfuzzer/releases)
- [Changelog](https://github.com/rust-fuzz/libfuzzer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-fuzz/libfuzzer/commits/0.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-26 12:07:51 +00:00
Rob Bradford
f8875acec2 misc: Bulk upgrade dependencies
In particular update for the vmm-sys-util upgrade and all the other
dependent packages. This requires an updated forked version of
kvm-bindings (due to updated vfio-ioctls) but allowed the removal of our
forked version of kvm-ioctls.

The changes to the API from kvm-ioctls and vmm-sys-util required some
other minor changes to the code.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-26 11:31:08 +00:00
Sebastien Boeuf
fa8fcf5f4c vhost: Move to upstream crate
The vhost crate from rust-vmm is ready, which is why we do the switch
from the Cloud Hypervisor fork to the upstream crate.

At the same time, we rename the crate from vhost_rs to vhost.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-25 11:20:41 +01:00
dependabot-preview[bot]
3e847112db build(deps): bump once_cell from 1.6.0 to 1.7.0
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.6.0 to 1.7.0.
- [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.6.0...v1.7.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-24 19:43:07 +00:00
Sebastien Boeuf
a0a89b1346 pci, vmm: Move to upstream vfio-ioctls crate
This commit moves both pci and vmm code from the internal vfio-ioctls
crate to the upstream one from the rust-vmm project.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-24 08:02:37 +01:00
Sebastien Boeuf
aee1155870 virtio-devices, vmm: Move to ExternalDmaMapping from vm-device
Now that ExternalDmaMapping is defined in vm-device, let's use it from
there.

This commit also defines the function get_host_address_range() to move
away from the vfio-ioctls dependency.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-24 08:02:37 +01:00
Sebastien Boeuf
5bd05b1af0 vm-device: Move ExternalDmaMapping trait out of vfio-ioctls
By moving the trait and its VFIO implementation out of vfio-ioctls, we
give anticipate for the move to the vfio-ioctls from rust-vmm.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-24 08:02:37 +01:00
Rob Bradford
727287b69d build: Drop aarch64 cross-build
This has been lagging behind on an older Rust version and we have
enough coverage from our Jenkins CI agent.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-23 11:07:48 +00:00
Rob Bradford
deedfcdc35 vmm: Improve restore error message about URL conversion
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-23 11:07:48 +00:00
Rob Bradford
2122233047 build: Remove "wait-timeout" dependency to dev-dependencies
This is only use in the integration test and was erroneously included in
the main binary dependencies.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-23 11:07:48 +00:00
Rob Bradford
afce21ba59 arch: Run interrupt tests
The interrupt tests were not being run as they were erroneously under a
feature guard that does not exist in arch.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-23 11:07:48 +00:00
Rob Bradford
ade5097878 arch: use libc::getrandom() instead of rand crate
This removes the last use of rand in our tree and the removal of several
dependencies.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-23 11:07:48 +00:00
Rob Bradford
24922ce1e3 tests: Move integration tests to vmm_sys_util::tempdir::TempDir
This removes the dependency on "tempdir" which in turn depends on the
large rand dependency chain.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-23 11:07:48 +00:00
Rob Bradford
c1be41bfbf net_util: Replace use of rand crate with libc::getrandom()
The rand crate provides a full cross platform true cryptographic random
number implementation. As such it brings it lots of othe dependencies
and increases our binary size and compile time. This is excessive for
generating a MAC address.

From the cargo tree output:

│   │   ├── rand v0.8.3
│   │   │   ├── libc v0.2.86
│   │   │   ├── rand_chacha v0.3.0
│   │   │   │   ├── ppv-lite86 v0.2.10
│   │   │   │   └── rand_core v0.6.0
│   │   │   │       └── getrandom v0.2.0
│   │   │   │           ├── cfg-if v0.1.10
│   │   │   │           └── libc v0.2.86
│   │   │   └── rand_core v0.6.0 (*)

And cargo bloat:

 0.0%   0.4% 40.4KiB rand_chacha rand_chacha::guts::refill_wide::impl_sse2
 0.0%   0.4% 40.0KiB rand_chacha rand_chacha::guts::refill_wide::impl_ssse3
 0.0%   0.3% 37.6KiB rand_chacha rand_chacha::guts::refill_wide::impl_avx
 0.0%   0.3% 37.2KiB rand_chacha rand_chacha::guts::refill_wide::impl_sse41
 0.0%   0.2% 26.1KiB rand_chacha rand_chacha::guts::refill_wide::impl_avx2

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-23 11:07:48 +00:00
Bo Chen
d361fc1a36 vmm: config: Fix and complete the help info for the '--disk' option
The help information displayed for our `--disk` option is incorrect and
incomplete, e.g. missing the `direct` and `poll_queue` field.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-02-23 08:55:33 +01:00
Wei Liu
49214cf02b hypervisor: emulator: fix MOVZX
According to Intel's mnemonic (which is used by iced-x86) the first
argument is destination while the second is source.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-02-23 07:42:33 +01:00
Rob Bradford
d78b2ec8b5 tests: Use vmm_sys_util::tempfile::Tempfile in integration tests
This removes the requirement for an extra crate and simplifies the
dependency chain.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-22 14:29:53 +01:00
Rob Bradford
946c484590 devices: Remove dependency on tempfile crate
This was completely unused.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-22 14:29:53 +01:00
Rob Bradford
cd700bf449 virtio-devices: Remove dependency on tempfile crate
This was completely unused.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-22 14:29:53 +01:00
Rob Bradford
cf7a05ecb5 block_util: Use vmm_sys_util::tempfile::Tempfile
This removes the requirement for an extra crate.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-22 14:29:53 +01:00
Rob Bradford
0497a7c311 qcow: Use vmm_sys_util::tempfile::Tempfile
This removes the requirement for an extra crate.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-22 14:29:53 +01:00
Rob Bradford
05a2b3fac2 vmm: Remove "tempfile" dependency from vmm
This was completely unused.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-22 14:29:53 +01:00
dependabot-preview[bot]
d33c0563af build(deps): bump once_cell from 1.5.2 to 1.6.0
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.5.2 to 1.6.0.
- [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.5.2...v1.6.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-22 13:28:54 +00:00
Sebastien Boeuf
4ed0e1a3c8 net_util: Simplify TX/RX queue handling
The main idea behind this commit is to remove all the complexity
associated with TX/RX handling for virtio-net. By using writev() and
readv() syscalls, we could get rid of intermediate buffers for both
queues.

The complexity regarding the TAP registration has been simplified as
well. The RX queue is only processed when some data are ready to be
read from TAP. The event related to the RX queue getting more
descriptors only serves the purpose to register the TAP file if it's not
already.

With all these simplifications, the code is more readable but more
performant as well. We can see an improvement of 10% for a single
queue device.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-22 10:39:23 +00:00
dependabot-preview[bot]
5ed2a654e8 build(deps): bump generator from 0.6.23 to 0.6.24
Bumps [generator](https://github.com/Xudong-Huang/generator-rs) from 0.6.23 to 0.6.24.
- [Release notes](https://github.com/Xudong-Huang/generator-rs/releases)
- [Commits](https://github.com/Xudong-Huang/generator-rs/compare/0.6.23...0.6.24)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-22 06:30:32 +00:00
dependabot-preview[bot]
ae04fe432c build(deps): bump signal-hook from 0.3.4 to 0.3.6
Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.3.4 to 0.3.6.
- [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.4...v0.3.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-21 09:36:30 +00:00
dependabot-preview[bot]
c8d142eb55 build(deps): bump crossbeam-utils from 0.8.1 to 0.8.2
Bumps [crossbeam-utils](https://github.com/crossbeam-rs/crossbeam) from 0.8.1 to 0.8.2.
- [Release notes](https://github.com/crossbeam-rs/crossbeam/releases)
- [Changelog](https://github.com/crossbeam-rs/crossbeam/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-utils-0.8.1...crossbeam-utils-0.8.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-21 09:36:12 +00:00
dependabot-preview[bot]
8533d63514 build(deps): bump cc from 1.0.66 to 1.0.67
Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.66 to 1.0.67.
- [Release notes](https://github.com/alexcrichton/cc-rs/releases)
- [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.66...1.0.67)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-19 22:54:50 +00:00
Muminul Islam
0ef69fa592 tests: Use constant instead of static value for windows image name
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2021-02-19 10:09:23 +00:00
Muminul Islam
29f924405a scripts: Check if windows image is in the host
Currently script does not exit early if the image/firmware not present
in the host. We should not progress further if the images are not pre
downloaded.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2021-02-19 10:09:23 +00:00
Muminul Islam
282134a490 scripts: Use variable for with windows image file
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2021-02-19 10:09:23 +00:00
dependabot-preview[bot]
1fbdca16bf build(deps): bump form_urlencoded from 1.0.0 to 1.0.1
Bumps [form_urlencoded](https://github.com/servo/rust-url) from 1.0.0 to 1.0.1.
- [Release notes](https://github.com/servo/rust-url/releases)
- [Commits](https://github.com/servo/rust-url/compare/v1.0.0...percent-encoding-v1.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-19 09:53:49 +00:00
Rob Bradford
32a2000ecc build: Only build the {kvm,mshv}-{ioctls,bindings} needed
This simplifies the Cloud Hypervisor dependency chain slightly.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-19 08:27:30 +01:00
dependabot-preview[bot]
6a499f02d9 build(deps): bump linux-loader from 2855be1 to 4ab9dad
Bumps [linux-loader](https://github.com/rust-vmm/linux-loader) from `2855be1` to `4ab9dad`.
- [Release notes](https://github.com/rust-vmm/linux-loader/releases)
- [Commits](2855be15a7...4ab9dade2c)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-19 07:14:55 +00:00
dependabot-preview[bot]
0a9c052ebd build(deps): bump thiserror from 1.0.23 to 1.0.24
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.23 to 1.0.24.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.23...1.0.24)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-19 07:14:39 +00:00
dependabot-preview[bot]
bfb12b7777 build(deps): bump url from 2.2.0 to 2.2.1
Bumps [url](https://github.com/servo/rust-url) from 2.2.0 to 2.2.1.
- [Release notes](https://github.com/servo/rust-url/releases)
- [Commits](https://github.com/servo/rust-url/compare/v2.2.0...v2.2.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-18 21:56:54 +00:00
Rob Bradford
c89095ab85 virtio-devices: Report events for virtio device activation and reset
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-18 16:15:13 +00:00
Rob Bradford
9260c4c10e vmm: Use event!() for some key VM actions
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-18 16:15:13 +00:00
Rob Bradford
4822ed79e1 main: Add "--monitor-fd" to write structured event data to
If supplied then structured JSON event data will be written to that file
descriptor.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-18 16:15:13 +00:00
Rob Bradford
ddbef7450d event_monitor: Add new crate for event reporting
This crate exposes the abililty for the VMM to set a file that events
should be written to. The event!() macro provides an interface to report
those events allowing the specification of an event source, an event
type and optional extra data. This will be written to the provided file
descriptor as JSON data.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-18 16:15:13 +00:00
Rob Bradford
c1d9edbfc0 vmm: seccomp: Add getrandom to vCPU thread filter
This can be triggered upon device reset.

Fixes: #2278

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-18 16:15:13 +00:00
dependabot-preview[bot]
0d209e135e build(deps): bump idna from 0.2.1 to 0.2.2
Bumps [idna](https://github.com/servo/rust-url) from 0.2.1 to 0.2.2.
- [Release notes](https://github.com/servo/rust-url/releases)
- [Commits](https://github.com/servo/rust-url/compare/v0.2.1...idna-v0.2.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-18 09:26:35 +00:00
Wei Liu
e22b6ec768 hypervisor: x86: emulate MOVS instruction
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-02-17 09:36:19 +01:00
Wei Liu
b59243f6cf hypervisor: mshv: support reading and writing guest memory in emulator
We don't have an easy way to figure out if a GPA points to normal memory
or device memory, but the guest's normal memory regions shouldn't
overlap with device regions. We can simply try to do a normal memory
read / write, and proceed to do device memory read / write if that
fails.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-02-17 09:36:19 +01:00
Rob Bradford
07a09eda27 hypervisor: kvm: Remove whitespace from use statements
This allows cargo fmt to correctly order the statements.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-16 18:38:57 +01:00
Rob Bradford
38c41a5074 vmm: memory_manager: Extract code for allocating new memory
This function can then be used by the TDX code to allocate the memory at
specific locations required for the TDVF to run from.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-16 18:38:57 +01:00
Rob Bradford
6e4c90f305 arch: Include "thiserror" crate as well as "anyhow"
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-16 18:38:57 +01:00
Rob Bradford
707bb0ba72 vmm: Simplify return path of vm_boot
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-16 18:38:57 +01:00
Wei Liu
29881a2d6a hypervisor: mshv: explicitly skip a few IO ports
OVMF would use string IO on those ports. String IO has not been
implemented, so that leads to panics.

Skip them explicitly in MSHV. Leave a long-ish comment in code to
explain the situation. We should properly implement string IO once it
becomes feasible / necessary.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-02-16 10:04:58 +01:00
Rob Bradford
a330a1569a arch, arch_gen, hypervisor: Remove some unnecessary clippy attributes
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-15 18:03:27 +01:00
Wei Liu
cf6480f012 hypervisor: mshv: drop some clippy attributes
They were used to suppress warnings during development. At this stage
they aren't needed anymore.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-02-15 14:52:26 +01:00
Bo Chen
a838d0bde1 scripts, tests: Rustify the network setup commands for tests
Fixes: #2218

Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-02-15 08:34:23 +00:00
Rob Bradford
f58b6f8417 build, release-notes.md, rpm: Release 0.13.0
Update version numbers and release notes for new release.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-12 10:38:48 +00:00
dependabot-preview[bot]
71ae9cfe06 build(deps): bump quote from 1.0.8 to 1.0.9
Bumps [quote](https://github.com/dtolnay/quote) from 1.0.8 to 1.0.9.
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.8...1.0.9)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-12 08:16:19 +00:00
dependabot-preview[bot]
f0b7a09a49 build(deps): bump env_logger from 0.8.2 to 0.8.3
Bumps [env_logger](https://github.com/env-logger-rs/env_logger) from 0.8.2 to 0.8.3.
- [Release notes](https://github.com/env-logger-rs/env_logger/releases)
- [Changelog](https://github.com/env-logger-rs/env_logger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/env-logger-rs/env_logger/compare/v0.8.2...v0.8.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-12 08:15:55 +00:00
Rob Bradford
bc84a1c79b build: Remove nested matches
Update for clippy in Rust 1.50.0:

error: Unnecessary nested match
   --> vmm/src/vm.rs:419:17
    |
419 | /                 if let vm_device::BusError::MissingAddressRange = e {
420 | |                     warn!("Guest MMIO write to unregistered address 0x{:x}", gpa);
421 | |                 }
    | |_________________^
    |
    = note: `-D clippy::collapsible-match` implied by `-D warnings`
help: The outer pattern can be modified to include the inner pattern.
   --> vmm/src/vm.rs:418:17
    |
418 |             Err(e) => {
    |                 ^ Replace this binding
419 |                 if let vm_device::BusError::MissingAddressRange = e {
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ with this pattern
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-11 18:18:44 +00:00
Rob Bradford
9c5be6f660 build: Remove unnecessary Result<> returns
If the function can never return an error this is now a clippy failure:

error: this function's return value is unnecessarily wrapped by `Result`
   --> virtio-devices/src/watchdog.rs:215:5
    |
215 | /     fn set_state(&mut self, state: &WatchdogState) -> io::Result<()> {
216 | |         self.common.avail_features = state.avail_features;
217 | |         self.common.acked_features = state.acked_features;
218 | |         // When restoring enable the watchdog if it was previously enabled. We reset the timer
...   |
223 | |         Ok(())
224 | |     }
    | |_____^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-11 18:18:44 +00:00
Rob Bradford
8e9a5a0dbb vm-migration: Use vm-memory's ByteValued instead of own AsBytes
This addresses a newly added clippy issue:

error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name
  --> vm-migration/src/protocol.rs:57:34
   |
57 |     fn as_mut_bytes<T: Sized>(p: &mut T) -> &mut [u8] {
   |                                  ^^^^^^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention

error: aborting due to 2 previous errors

error: could not compile `vm-migration`

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-11 18:18:44 +00:00
Bo Chen
d561b45552 tests: Add integration test test_macvtap
This integration test mimics the instructions from
`docs/macvtap-bridge.md`.

Fixes: #2215

Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-02-11 15:25:32 +00:00
Sebastien Boeuf
9353856426 vmm: Fix seccomp filters for vCPUs
Depending on the host OS the code for looking up the time for the CMOS
make require extra syscalls to be permitted for the vCPU thread.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-11 11:24:57 +00:00
Sebastien Boeuf
9af477e964 pci: vfio: Check VFIO device interrupt's support
In case the VFIO device does not support MSI or MSI-X, the capabilities
should not be parsed, avoiding the exposure of unsupported capabilities.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-10 17:34:56 +00:00
Sebastien Boeuf
27515a6ec4 pci: vfio: Propagate errors when enabling interrupts
Make sure to propagate the error coming from VfioDevice when trying to
enable INTx, MSI or MSI-X interrutps.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-10 17:34:56 +00:00
Sebastien Boeuf
169a6bb83b docs: vfio: Remove documentation regarding VFIO limitations
Since INTx is now supported for VFIO PCI devices, there is no more
limitations regarding VFIO, which means the documentation must be
updated accordingly.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-10 17:34:56 +00:00
Sebastien Boeuf
19167e7647 pci: vfio: Implement INTx support
With all the preliminary work done in the previous commits, we can
update the VFIO implementation to support INTx along with MSI and MSI-X.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-10 17:34:56 +00:00
Sebastien Boeuf
2cdc3e3546 vmm: device_manager: Add PCI routing table to ACPI
Here we are adding the PCI routing table, commonly called _PRT, to the
ACPI DSDT. For simplification reasons, we chose not to implement PCI
links as this involves dynamic decision from the guest OS, which result
in lots of complexity both from an AML perspective and from a device
manager perspective.

That's why the _PRT creates a static list of 32 entries, each assigned
with the IRQ number previously reserved by the device manager.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-10 17:34:56 +00:00
Sebastien Boeuf
de9471fc72 vmm: device_manager: Allocate IRQs for PCI devices
In order to support INTx for PCI devices, each PCI device must be
assigned an IRQ. This is preliminary work to reserve 8 IRQs which will
be shared across the 32 PCI devices.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-10 17:34:56 +00:00
Sebastien Boeuf
b5450ca72c vmm: device_manager: Store legacy interrupt manager
In anticipation for accessing the legacy interrupt manager from the
function creating a VFIO PCI device, we store it as part of the
DeviceManager, to make it available for all methods.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-10 17:34:56 +00:00
Sebastien Boeuf
8008aad545 vmm: device_manager: Don't pass the MSI interrupt manager around
The DeviceManager already has a hold onto the MSI interrupt manager,
therefore there's no need to pass it through every function. Instead,
let's simplify the code by using the attribute from DeviceManager's
instance.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-10 17:34:56 +00:00
Sebastien Boeuf
3bd47ffdc1 interrupt: Add a notifier method to the InterruptController
Both GIC and IOAPIC must implement a new method notifier() in order to
provide the caller with an EventFd corresponding to the IRQ it refers
to.

This is needed in anticipation for supporting INTx with VFIO PCI
devices.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-10 17:34:56 +00:00
Sebastien Boeuf
acfbee5b7a interrupt: Make notifier function return Option<EventFd>
In anticipation for supporting the notifier function for the legacy
interrupt source group, we need this function to return an EventFd
instead of a reference to this same EventFd.

The reason is we can't return a reference when there's an Arc<Mutex<>>
involved in the call chain.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-10 17:34:56 +00:00
Wei Liu
62c6efb2e5 build: fix cargo fuzz build
The dependency on vm-memory was not updated by dependabot.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-02-10 14:42:41 +01:00
Wei Liu
aec0d309ee hypervisor: emulator: also set ES segment in MockVMM
Some instructions, such as MOVS, need a valid ES segment.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-02-10 11:31:03 +00:00
Wei Liu
5fc12862e6 hypervisor, vmm: minor changes to VmmOps
Swap the last two parameters of guest_mem_{read,write} to be consistent
with other read / write functions.

Use more descriptive parameter names.

No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-02-10 11:31:03 +00:00
Wei Liu
f4159ca016 hypervisor: emulator: drop useless set_ip calls
The instruction pointer is already pointing at the instruction being
emulated.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-02-10 11:31:03 +00:00
dependabot-preview[bot]
6d63018d9f build(deps): bump vm-memory from 0.4.0 to 0.5.0
Bumps [vm-memory](https://github.com/rust-vmm/vm-memory) from 0.4.0 to 0.5.0.
- [Release notes](https://github.com/rust-vmm/vm-memory/releases)
- [Changelog](https://github.com/rust-vmm/vm-memory/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-vmm/vm-memory/compare/v0.4.0...v0.5.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-10 11:30:05 +00:00
dependabot-preview[bot]
073e0f979b build(deps): bump vfio-ioctls from 49cc362 to 6ea1b93
Bumps [vfio-ioctls](https://github.com/cloud-hypervisor/vfio-ioctls) from `49cc362` to `6ea1b93`.
- [Release notes](https://github.com/cloud-hypervisor/vfio-ioctls/releases)
- [Commits](49cc3626f6...6ea1b934bb)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-10 07:01:43 +00:00
Rob Bradford
50a995b63d vmm: Rename patch_cpuid() to generate_common_cpuid()
This reflects that it generates CPUID state used across all vCPUs.
Further ensure that errors from this function get correctly propagated.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-09 16:02:25 +00:00
Rob Bradford
ccdea0274c vmm, arch: Move KVM HyperV emulation handling to shared CPUID code
Move the code for populating the CPUID with KVM HyperV emulation details from
the per-vCPU CPUID handling code to the shared CPUID handling code.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-09 16:02:25 +00:00
Rob Bradford
688ead51c6 vmm, arch: Move CPU identification handling to shared CPUID code
Move the code for populating the CPUID with details of the CPU
identification from the per-vCPU CPUID handling code to the shared CPUID
handling code.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-09 16:02:25 +00:00
Rob Bradford
9792c9aafa vmm, arch: Move max_phys_bits handling to shared CPUID code
Move the code for populating the CPUID with details of the maximum
address space from the per-vCPU CPUID handling code to the shared CPUID
handling code.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-09 16:02:25 +00:00
William Douglas
48963e322a Enable pty console
Add the ability for cloud-hypervisor to create, manage and monitor a
pty for serial and/or console I/O from a user. The reasoning for
having cloud-hypervisor create the ptys is so that clients, libvirt
for example, could exit and later re-open the pty without causing I/O
issues. If the clients were responsible for creating the pty, when
they exit the main pty fd would close and cause cloud-hypervisor to
get I/O errors on writes.

Ideally the main and subordinate pty fds would be kept in the main
vmm's Vm structure. However, because the device manager owns parsing
the configuration for the serial and console devices, the information
is instead stored in new fields under the DeviceManager structure
directly.

From there hooking up the main fd is intended to look as close to
handling stdin and stdout on the tty as possible (there is some future
work ahead for perhaps moving support for the pty into the
vmm_sys_utils crate).

The main fd is used for reading user input and writing to output of
the Vm device. The subordinate fd is used to setup raw mode and it is
kept open in order to avoid I/O errors when clients open and close the
pty device.

The ability to handle multiple inputs as part of this change is
intentional. The current code allows serial and console ptys to be
created and both be used as input. There was an implementation gap
though with the queue_input_bytes needing to be modified so the pty
handlers for serial and console could access the methods on the serial
and console structures directly. Without this change only a single
input source could be processed as the console would switch based on
its input type (this is still valid for tty and isn't otherwise
modified).

Signed-off-by: William Douglas <william.r.douglas@gmail.com>
2021-02-09 10:03:28 +00:00
dependabot-preview[bot]
a59fbf0e37 build(deps): bump unicode-normalization from 0.1.16 to 0.1.17
Bumps [unicode-normalization](https://github.com/unicode-rs/unicode-normalization) from 0.1.16 to 0.1.17.
- [Release notes](https://github.com/unicode-rs/unicode-normalization/releases)
- [Commits](https://github.com/unicode-rs/unicode-normalization/compare/v0.1.16...v0.1.17)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-09 06:43:17 +00:00
Rob Bradford
a6b839b35c build: Update to latest kvm-ioctls
Update the version of the fork pointed to which has been rebased on the
latest upstream.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-08 18:16:18 +00:00
dependabot-preview[bot]
aa3d5cfbfe build(deps): bump libc from 0.2.85 to 0.2.86
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.85 to 0.2.86.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.85...0.2.86)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-08 16:19:06 +00:00
Wei Liu
ddd0552c83 virtio-devices: vhost-user-net: unpark control queue thread in resume
This thread is virtio-net specific, so it is not handled in the common
virtio device code.

The non-vhost implementation resumes the thread itself. Do the same
thing for vhost-user-net.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-02-08 16:16:13 +00:00
Wei Liu
1fc8c9165a vmm: drop two unused errors
Their last users were gone in af3c6c34c3.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-02-08 16:15:31 +00:00
dependabot-preview[bot]
47f47ad53f build(deps): bump iced-x86 from 1.10.0 to 1.10.3
Bumps [iced-x86](https://github.com/0xd4d/iced) from 1.10.0 to 1.10.3.
- [Release notes](https://github.com/0xd4d/iced/releases)
- [Commits](https://github.com/0xd4d/iced/compare/v1.10.0...v1.10.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-08 07:24:59 +00:00
dependabot-preview[bot]
69d1186ccb build(deps): bump serde_json from 1.0.61 to 1.0.62
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.61 to 1.0.62.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.61...v1.0.62)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-06 10:01:35 +00:00
dependabot-preview[bot]
d0601a1473 build(deps): bump idna from 0.2.0 to 0.2.1
Bumps [idna](https://github.com/servo/rust-url) from 0.2.0 to 0.2.1.
- [Release notes](https://github.com/servo/rust-url/releases)
- [Commits](https://github.com/servo/rust-url/compare/idna-v0.2.0...v0.2.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-05 11:17:52 +00:00
Rob Bradford
b91b829a28 openapi: Update API spec to include hugepage_size parameter
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-05 09:24:02 +00:00
Rob Bradford
7928a697dc vmm: Support configurable huge pages in MemoryManager
Use the newly added hugepages_size option if provided by the user to
pick a huge page size when creating the memfd region. If none is
specified use the system default.

Sadly different huge pages cannot be tested by an integration test as
creating a pool of the non-default size cannot be done at runtime
(requires kernel to be booted with certain parameters.)

TETS=Manually tested with a kernel booted with both 1GiB and 2MiB huge
pages (hugepagesz=1G hugepages=1 hugepagesz=2M hugepages=512)

Fixes: #2230

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-05 09:24:02 +00:00
Rob Bradford
b5fb744828 docs: Update documentation for hugepage_size option
Including a warning that the user is respsonsible for ensuring that they
have sufficient pages of the specified size.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-05 09:24:02 +00:00
Rob Bradford
29607f38ad vmm: config: Add a hugepage_size option
This allows the user to use an alternative huge page size otherwise the
default size will be used.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-05 09:24:02 +00:00
Rob Bradford
9c3a73706f vmm: config: Remove ineffectual code from test
Remove a change the invalid configuration that is not ever tested again.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-02-05 09:24:02 +00:00
Muminul Islam
024675d1d8 scripts: error exit if aarch64 test is run on MSHV
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2021-02-05 09:22:58 +00:00
dependabot-preview[bot]
2c913b8130 build(deps): bump thread_local from 1.1.2 to 1.1.3
Bumps [thread_local](https://github.com/Amanieu/thread_local-rs) from 1.1.2 to 1.1.3.
- [Release notes](https://github.com/Amanieu/thread_local-rs/releases)
- [Commits](https://github.com/Amanieu/thread_local-rs/compare/v1.1.2...v1.1.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-04 20:53:44 +00:00
Sebastien Boeuf
c397c9c95e vmm, virtio-devices: mem: Don't use MADV_DONTNEED on hugepages
This commit introduces a new information to the VirtioMemZone structure
in order to know if the memory zone is backed by hugepages.

Based on this new information, the virtio-mem device is now able to
determine if madvise(MADV_DONTNEED) should be performed or not. The
madvise documentation specifies that MADV_DONTNEED advice will fail if
the memory range has been allocated with some hugepages.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
Signed-off-by: Hui Zhu <teawater@antfin.com>
2021-02-04 17:52:30 +00:00
Sebastien Boeuf
54f814f34a virtio-devices: mem: Refactor MemEpollHandler
This commit performs some refactoring to make all functions a method
from a specific object, and in particular methods for MemEpollHandler.

The point is to simplify the code to make it more readable.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-04 17:52:30 +00:00
Sebastien Boeuf
ad8adcb955 virtio-devices: mem: Adjust based on specification
Adjust the code to comply better with the virtio-mem specification by
adding some validation for the virtio-mem configuration, but also by
updating the virtio-mem configuration itself.

Nowhere in the virtio-mem specification is stated the usable region size
must be adjusted everytime the plugged size changes. For simplification
reason, and without going against the specification, the usable region
size is now kept static, setting its value to the size of the whole
region.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-04 17:52:30 +00:00
Sebastien Boeuf
f24094392e virtio-devices: mem: Improve semantic around Resize object
By introducing a ResizeSender object, we avoid having a Resize clone
with a different content than the original Resize object.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-04 17:52:30 +00:00
Samuel Ortiz
eee218f1f5 hypervisor: emulator: Add MOVZX unit tests
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2021-02-03 14:11:18 +01:00
Samuel Ortiz
5ada3f59c8 hypervisor: emulator: Emulate MOVZX
MOV R/RM is a special case of MOVZX, so we generalize the mov_r_rm macro
to make it support both instructions.

Fixes: #2227

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2021-02-03 14:11:18 +01:00
dependabot-preview[bot]
89008a49cf build(deps): bump libc from 0.2.84 to 0.2.85
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.84 to 0.2.85.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.84...0.2.85)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-02 07:47:41 +00:00
dependabot-preview[bot]
295f4df7bf build(deps): bump ssh2 from 0.9.0 to 0.9.1
Bumps [ssh2](https://github.com/alexcrichton/ssh2-rs) from 0.9.0 to 0.9.1.
- [Release notes](https://github.com/alexcrichton/ssh2-rs/releases)
- [Commits](https://github.com/alexcrichton/ssh2-rs/compare/0.9.0...0.9.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-01 18:48:26 +00:00
dependabot-preview[bot]
769194cac8 build(deps): bump libssh2-sys from 0.2.20 to 0.2.21
Bumps [libssh2-sys](https://github.com/alexcrichton/ssh2-rs) from 0.2.20 to 0.2.21.
- [Release notes](https://github.com/alexcrichton/ssh2-rs/releases)
- [Commits](https://github.com/alexcrichton/ssh2-rs/compare/libssh2-sys-0.2.20...libssh2-sys-0.2.21)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-01 18:13:04 +00:00
Sebastien Boeuf
13a3ac6a77 block_util: Add unit testing for VHD format
The vhd module is the implementation of the VHD specification, which is
why it is important to unit test it.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-01 13:45:08 +00:00
Sebastien Boeuf
b26777cb01 ci: Add integration test for VHD format
Let's create a fixed VHD disk file from the existing RAW file thanks to
qemu-img, and create a new integration test to validate that
Cloud-Hypervisor can boot VHD disk image.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-01 13:45:08 +00:00
Sebastien Boeuf
24c8cce012 block_util: Add synchronous support for fixed VHD disk files
Relying on the simplified version of the synchronous support for RAW
disk files, the new fixed_vhd_sync module in the block_util crate
introduces the synchronous support for fixed VHD disk files.

With this patch, the fixed VHD support is complete as it is implemented
in both synchronous and asynchronous versions.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-01 13:45:08 +00:00
Sebastien Boeuf
c6854c5a97 block_util: Simplify RAW synchronous implementation
Using directly preadv and pwritev, we can simply use a RawFd instead of
a file, and we don't need to use the more complex implementation from
the qcow crate.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-01 13:45:08 +00:00
Sebastien Boeuf
b2e5dbaecb block_util, vmm: Add fixed VHD asynchronous implementation
This commit adds the asynchronous support for fixed VHD disk files.

It introduces FixedVhd as a new ImageType, moving the image type
detection to the block_util crate (instead of qcow crate).

It creates a new vhd module in the block_util crate in order to handle
VHD footer, following the VHD specification.

It creates a new fixed_vhd_async module in the block_util crate to
implement the asynchronous version of fixed VHD disk file. It relies on
io_uring.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-01 13:45:08 +00:00
Muminul Islam
5bbf2dca80 vmm: Remove unneeded return statement
This unneeded return statement giving clippy warnings

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2021-01-30 08:58:09 +00:00
dependabot-preview[bot]
1df952726a build(deps): bump libc from 0.2.83 to 0.2.84
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.83 to 0.2.84.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-29 06:21:38 +00:00
Rob Bradford
9ea087597f vmm: acpi: Ensure field size address matches ResourceTag
dsdt.dsl    960:             CreateDWordField (MR64, \_SB.MHPC.MCRS._Y00._MIN, MINL)  // _MIN: Minimum Base Address
Warning  3128 -                              ResourceTag larger than Field ^  (Size mismatch, Tag: 64 bits, Field: 32 bits)

dsdt.dsl    962:             CreateDWordField (MR64, \_SB.MHPC.MCRS._Y00._MAX, MAXL)  // _MAX: Maximum Base Address
Warning  3128 -                              ResourceTag larger than Field ^  (Size mismatch, Tag: 64 bits, Field: 32 bits)

dsdt.dsl    964:             CreateDWordField (MR64, \_SB.MHPC.MCRS._Y00._LEN, LENL)  // _LEN: Length
Warning  3128 -                              ResourceTag larger than Field ^  (Size mismatch, Tag: 64 bits, Field: 32 bits)

Fixes: #2216

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-28 14:30:34 +01:00
Rob Bradford
952f9bd3fe vmm: acpi: Remove incorrect return statement
_EJx built in should not return.

dsdt.dsl    813:                 Return (CEJ0 (0x00))
Warning  3104 -                            ^ Reserved method should not return a value (_EJ0)

dsdt.dsl    813:                 Return (CEJ0 (0x00))
Error    6080 -                            ^ Called method returns no value

Fixes: #2216

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-28 14:30:34 +01:00
Rob Bradford
c29caf2a85 vmm: acpi: Fix incorrect mutex timeout value
The mutex timeout should be 0xffff rather than 0xfff to disable the
timeout feature.

dsdt.dsl    745:             Acquire (\_SB.PRES.CPLK, 0x0FFF)
Warning  3130 -                                           ^ Result is not used, possible operator timeout will be missed

dsdt.dsl    767:             Acquire (\_SB.PRES.CPLK, 0x0FFF)
Warning  3130 -                                           ^ Result is not used, possible operator timeout will be missed

dsdt.dsl    775:             Acquire (\_SB.PRES.CPLK, 0x0FFF)
Warning  3130 -                                           ^ Result is not used, possible operator timeout will be missed

Fixes: #2216

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-28 14:30:34 +01:00
Bo Chen
5fbeacabad tests: Remove manual delete of the TAP interface in test_tap_from_fd
By using `net_util::open_tap` to create the TAP interface, the created
interface will be deleted when the returned variable (`net_utils::Tap`)
is dropped.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-01-28 09:11:39 +00:00
Bo Chen
f7502057d9 tests: Extend test_tap_from_fd() with using multiple TAP fds
Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-01-28 09:11:39 +00:00
Bo Chen
ff54909d2c vmm: openapi: Update the fd field of the NetConfig definition
Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-01-28 09:11:39 +00:00
Bo Chen
6664e5a6e7 net_util, virtio-devices, vmm: Accept multiple TAP fds
This patch enables multi-queue support for creating virtio-net devices by
accepting multiple TAP fds, e.g. '--net fds=3:7'.

Fixes: #2164

Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-01-28 09:11:39 +00:00
Rob Bradford
5209026f52 tests: Port test_tap_from_fd to use net_util::open_tap
This removes the need for manually creating the interface and assigning
the IP.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-28 09:11:39 +00:00
Rob Bradford
5db9b0ec99 net_util: Support supplying flags to open_tap() helper
This helper can open a TAP device and configure the interface on it. If
the device needs to be opened multiple times for MQ then it also handles
that correctly.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-28 09:11:39 +00:00
Muminul Islam
c4fb0f36bd scripts: Use hypervisor variable instead of kvm
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2021-01-28 09:11:02 +00:00
Muminul Islam
9cdcbb5121 script: Modify unit tests to support mshv
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2021-01-28 09:11:02 +00:00
Muminul Islam
a194dad98c arch, vmm: Run KVM specific unit tests with kvm feature guard
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2021-01-28 09:11:02 +00:00
Muminul Islam
b339aa6b88 scripts: Export devices(/dev/kvm or /dev/mshv) based on hypervisor
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2021-01-28 09:11:02 +00:00
Sebastien Boeuf
276c9a10fd docs: Clarify VFIO limitations regarding NVIDIA cards
Because of the behavior of the NVIDIA proprietary driver, we can't
expect NVIDIA cards with only MSI support to be functioning correctly
after they've been passed through with Cloud-Hypervisor.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-28 09:10:45 +00:00
dependabot-preview[bot]
36360c7630 build(deps): bump libc from 0.2.82 to 0.2.83
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.82 to 0.2.83.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.82...0.2.83)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-28 06:30:03 +00:00
Wei Liu
b959849149 vmm: drop unnecessary semicolon
Building with 1.51 nightly produces the following warning:

warning: unnecessary trailing semicolon
   --> vmm/src/device_manager.rs:396:6
    |
396 |     };
    |      ^ help: remove this semicolon
    |
    = note: `#[warn(redundant_semicolons)]` on by default

warning: 1 warning emitted

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-01-27 14:43:20 +00:00
dependabot-preview[bot]
50a89c6808 build(deps): bump rand from 0.8.2 to 0.8.3
Bumps [rand](https://github.com/rust-random/rand) from 0.8.2 to 0.8.3.
- [Release notes](https://github.com/rust-random/rand/releases)
- [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/rand/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-27 13:26:04 +00:00
dependabot-preview[bot]
192d69d601 build(deps): bump log from 0.4.13 to 0.4.14
Bumps [log](https://github.com/rust-lang/log) from 0.4.13 to 0.4.14.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.13...0.4.14)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-27 12:48:52 +00:00
Rob Bradford
b8342ebeb4 scripts: Don't download container on help invocations
Delay downloading the container until it is being used.

Fixes: #2065

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-26 13:29:05 +01:00
Rob Bradford
58009af85d tests: Add clippy check for integration test building
Ensure that we try and keep the integration tests clippy clean.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-26 13:23:16 +01:00
dependabot-preview[bot]
0655f25da4 build(deps): bump serde from 1.0.121 to 1.0.123
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.121 to 1.0.123.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.121...v1.0.123)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-26 10:49:12 +00:00
dependabot-preview[bot]
2547f144cd build(deps): bump tinyvec from 1.1.0 to 1.1.1
Bumps [tinyvec](https://github.com/Lokathor/tinyvec) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/Lokathor/tinyvec/releases)
- [Changelog](https://github.com/Lokathor/tinyvec/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Lokathor/tinyvec/compare/v1.1.0...v1.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-26 09:43:10 +00:00
dependabot-preview[bot]
ec7700544c build(deps): bump serde_derive from 1.0.122 to 1.0.123
Bumps [serde_derive](https://github.com/serde-rs/serde) from 1.0.122 to 1.0.123.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.122...v1.0.123)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-26 09:42:42 +00:00
Rob Bradford
0c60fa8268 net_util: tests: Avoid trying to create TAP devices simultaneously
The unit tests ask the Linux kernel to generate a TAP device name on
demand by passing in a format string. I suspect, but haven't been able
to confirm that there might be a rare race that triggers when creating
lots of devices in a short period of time. This is appearing in our unit
test as the occassional flake of the test_tap_read() which although it
has successfully created the device it fails to set the IP address on it
when looking it back up by it's name.

Since this is the most frequent cause of failures on our CI use a lock
to ensure that multiple TAP devices are not created simultaneously.

Fixes: #2135

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-26 10:42:02 +01:00
Rob Bradford
76e15a4240 vmm: acpi: Support compiling ACPI code on aarch64
This skeleton commit brings in the support for compiling aarch64 with
the "acpi" feature ready to the ACPI enabling. It builds on the work to
move the ACPI hotplug devices from I/O ports to MMIO and conditionalises
any code that is x86_64 only (i.e. because it uses an I/O port.)

Filling in the aarch64 specific details in tables such as the MADT it
out of the scope.

See: #2178

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-26 15:19:02 +08:00
Vineeth Pillai
7659055eec mshv: Use in-kernel ioeventfd mechanism
Signed-off-by: Vineeth Pillai <viremana@linux.microsoft.com>
2021-01-25 21:20:29 +00:00
Vineeth Pillai
5209bd6120 mshv: Use in-kernel irqfd mechanism
Convert MshvIrqRoutingEntry functions to methods as well.

Signed-off-by: Vineeth Pillai <viremana@linux.microsoft.com>
2021-01-25 21:20:29 +00:00
Rob Bradford
c2acea5156 tests: Support filtering integration tests
e.g.

scripts/dev_cli.sh tests --integration -- --test-filter test_watchdog

This used to be supported by passing "$@" but was broken when multiple
hypervisor support was added.

Fixes: #2182

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-25 17:34:10 +00:00
Wei Liu
fd9972ecc5 hypervisor: fix exception vector numbers
According to Intel SDM, #DE should be 0 and #DB should be 1.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-01-25 16:39:08 +00:00
dependabot-preview[bot]
ca4ab99f42 build(deps): bump serde_derive from 1.0.121 to 1.0.122
Bumps [serde_derive](https://github.com/serde-rs/serde) from 1.0.121 to 1.0.122.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.121...v1.0.122)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-25 12:16:07 +00:00
dependabot-preview[bot]
977d824cf8 build(deps): bump syn from 1.0.59 to 1.0.60
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.59 to 1.0.60.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.59...1.0.60)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-25 09:23:17 +00:00
dependabot-preview[bot]
38fa630ce7 build(deps): bump thread_local from 1.1.1 to 1.1.2
Bumps [thread_local](https://github.com/Amanieu/thread_local-rs) from 1.1.1 to 1.1.2.
- [Release notes](https://github.com/Amanieu/thread_local-rs/releases)
- [Commits](https://github.com/Amanieu/thread_local-rs/compare/v1.1.1...v1.1.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-25 09:23:07 +00:00
Rob Bradford
a59b361058 resources: Use Rust 1.49.0 in container
This is the latest stable version.

Fixes: #2092

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-24 17:05:07 +00:00
dependabot-preview[bot]
fa5b5fd602 build(deps): bump serde from 1.0.120 to 1.0.121
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.120 to 1.0.121.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.120...v1.0.121)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-24 16:21:11 +00:00
dependabot-preview[bot]
7765398045 build(deps): bump serde_derive from 1.0.120 to 1.0.121
Bumps [serde_derive](https://github.com/serde-rs/serde) from 1.0.120 to 1.0.121.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.120...v1.0.121)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-24 15:37:25 +00:00
dependabot-preview[bot]
9282ad82b0 build(deps): bump syn from 1.0.58 to 1.0.59
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.58 to 1.0.59.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.58...1.0.59)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-23 11:58:14 +00:00
dependabot-preview[bot]
a09feecc36 build(deps): bump thread_local from 1.1.0 to 1.1.1
Bumps [thread_local](https://github.com/Amanieu/thread_local-rs) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/Amanieu/thread_local-rs/releases)
- [Commits](https://github.com/Amanieu/thread_local-rs/compare/v1.1.0...v1.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-23 11:57:46 +00:00
Sebastien Boeuf
060df69f07 block_util: Factorize common code for synchronous implementations
Since QCOW and RAW synchronous implementation are very close, it makes
sense to introduce some common functions that can be shared between
these two.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-22 16:10:34 +00:00
Sebastien Boeuf
f6c8e4b045 vmm: device_manager: Add info!() message about disk file backend
It might be useful debugging information for the user to know what kind
of disk file implementation is in use.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-22 16:10:34 +00:00
Sebastien Boeuf
2824642e80 virtio-devices: Rename BlockIoUring to Block
Now that BlockIoUring is the only implementation of virtio-block,
handling both synchronous and asynchronous backends based on the
AsyncIo trait, we can rename it to Block.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-22 16:10:34 +00:00
Sebastien Boeuf
41cfdb50cd virtio-devices: Remove virtio-block synchronous implementation
Now that both synchronous and asynchronous backends rely on the
asynchronous version of virtio-block (namely BlockIoUring), we can
get rid of the synchronous version (namely Block).

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-22 16:10:34 +00:00
Sebastien Boeuf
12e20effd7 block_util: Port synchronous QCOW file to AsyncIo trait
Based on the synchronous QCOW file implementation present in the qcow
crate, we created a new qcow_sync module in block_util that ports this
synchronous implementation to the AsyncIo trait.

The point is to reuse virtio-blk asynchronous implementation for both
synchronous and asynchronous backends.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-22 16:10:34 +00:00
Sebastien Boeuf
9fc86a91e2 block_util: Port synchronous RAW file to AsyncIo trait
Based on the synchronous RAW file implementation present in the qcow
crate, we created a new raw_sync module in block_util that ports this
synchronous implementation to the AsyncIo trait.

The point is to reuse virtio-blk asynchronous implementation for both
synchronous and asynchronous backends.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-22 16:10:34 +00:00
Sebastien Boeuf
da8ce25abf virtio-devices: Use asynchronous traits for virtio-blk io_uring
Based on the new DiskFile and AsyncIo traits, the implementation of
asynchronous block support does not have to be tied to io_uring anymore.
Instead, the only thing the virtio-blk implementation knows is that it
is using an asynchronous implementation of the underlying disk file.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-22 16:10:34 +00:00
Sebastien Boeuf
23e3b022eb block_util: Implement asynchronous traits for RAW disk file
This provides the implementation of DiskFile and AsyncIo for the RAW
file format.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-22 16:10:34 +00:00
Sebastien Boeuf
30033bdaea block_util: Add new traits for handling disk files asynchronously
Both DiskFile and AsyncIo traits are introduced to allow all kind of
files (RAW, QCOW, VHD) to be able to handle asynchronous access to the
underlying file.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-22 16:10:34 +00:00
Rob Bradford
d578c408b7 vmm: acpi: Move DeviceManager ACPI device to an MMIO address
Migrate the DeviceManager from a fixed I/O port address to an allocated
MMIO address.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-22 16:08:41 +01:00
Rob Bradford
55a3a38e14 vmm: acpi: Move CpuManager ACPI device to an MMIO address
Migrate the CpuManager from a fixed I/O port address to an allocated
MMIO address.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-22 16:08:41 +01:00
Rob Bradford
6006068951 vmm: acpi: Move MemoryManager ACPI device to an MMIO address
Migrate the MemoryManager from a fixed I/O port address to an allocated
MMIO address.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-22 16:08:41 +01:00
Rob Bradford
28ab6cea0e vmm: acpi: Move ACPI GED device to MMIO bus
Currently the GED control is in a fixed I/O port address but instead use
an MMIO address that has been chosen by the allocator.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-22 16:08:41 +01:00
Rob Bradford
4ebeeb1310 vmm: device_manager: Rename shutdown ACPI device
Rename the variable for the shutdown device to clarify it's purpose in
the function.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-22 16:08:41 +01:00
dependabot-preview[bot]
77f6cd5ef4 build(deps): bump mshv-bindings from 2ded6da to 3a7d7ba
Bumps [mshv-bindings](https://github.com/cloud-hypervisor/mshv) from `2ded6da` to `3a7d7ba`.
- [Release notes](https://github.com/cloud-hypervisor/mshv/releases)
- [Commits](2ded6daf97...3a7d7ba07e)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-22 07:09:54 +00:00
dependabot-preview[bot]
f2c2a44ca6 build(deps): bump backtrace from 0.3.55 to 0.3.56
Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.55 to 0.3.56.
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.55...0.3.56)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-21 17:18:29 +00:00
Bo Chen
8d418e1fca vmm: Refine the seccomp filter list for the vCPU thread
This patch refines the sccomp filter list for the vCPU thread, as we are
no longer spawning virtio-device threads from the vCPU thread.

Fixes: #2170

Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-01-21 09:41:40 +00:00
Rob Bradford
c90f77e399 virtio-devices: Enforce a minimum number of queues
Even though the driver can provide fewer queues than those advertised
for some device types their is a minimum number that is required for
operation.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-20 18:54:36 +01:00
Rob Bradford
a105089702 virtio-devices: Support driver programming fewer queues
It is permissable for the driver to program fewer queues than offered by
the device. Filter the queues so that only the ready ones are included
and check that they have valid addresses configured.

Fixes: #2136

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-20 18:54:36 +01:00
Rob Bradford
c366efc19e virtio-devices: block, block_io_uring: Don't assume max queue count
Don't assume that the number of queues provided match the number of
queues offered. The virtio spec allows the driver to program fewer
queues.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-20 18:54:36 +01:00
Rob Bradford
c9b68a3be6 .github: Simplify cross-build action
Remove unnecessary commands to simplify the cross-build action.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-20 18:51:42 +01:00
Xie Yongji
72b736153e vm-virtio: Fix update_avail_event() memory ordering
We should use full memory barrier to ensure both guest and us
can see the correct avail_idx and avail_event_idx. Something
like this pattern:

VM:                           CLH:
update vring.avail->idx       update avail_event_idx
mb()                          mb()
read avail_event_idx          read vring.avail->idx

Signed-off-by: Xie Yongji <xieyongji@bytedance.com>
2021-01-20 08:32:56 +01:00
dependabot-preview[bot]
79a2afe44e build(deps): bump serde from 1.0.119 to 1.0.120
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.119 to 1.0.120.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.119...v1.0.120)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-19 08:19:23 +00:00
dependabot-preview[bot]
7d299f1055 build(deps): bump serde_derive from 1.0.119 to 1.0.120
Bumps [serde_derive](https://github.com/serde-rs/serde) from 1.0.119 to 1.0.120.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.119...v1.0.120)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-19 07:37:46 +00:00
Rob Bradford
23f9ec50fb virtio-devices: Simplify virtio device reset
Rather than having to give and return the ioeventfd used for a device
clone them each time. This will make it simpler when we start handling
the driver enabling fewer queues than advertised by the device.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-18 15:05:54 +00:00
dependabot-preview[bot]
c99d3f70ac build(deps): bump signal-hook from 0.3.3 to 0.3.4
Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.3.3 to 0.3.4.
- [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/commits/v0.3.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-17 20:27:52 +00:00
dependabot-preview[bot]
33d339c406 build(deps): bump hermit-abi from 0.1.17 to 0.1.18
Bumps [hermit-abi](https://github.com/hermitcore/libhermit-rs) from 0.1.17 to 0.1.18.
- [Release notes](https://github.com/hermitcore/libhermit-rs/releases)
- [Commits](https://github.com/hermitcore/libhermit-rs/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-17 20:27:34 +00:00
Rob Bradford
22649c4a87 virtio-devices: Upon reset reap/join the device threads
We have killed the device thread by writing to the exit EventFd but we
should wait for them to quit to ensure consistency.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-14 17:25:14 +01:00
dependabot-preview[bot]
ef363d79fb build(deps): bump humantime from 2.0.1 to 2.1.0
Bumps [humantime](https://github.com/tailhook/humantime) from 2.0.1 to 2.1.0.
- [Release notes](https://github.com/tailhook/humantime/releases)
- [Commits](https://github.com/tailhook/humantime/compare/v2.0.1...v2.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-13 21:49:27 +00:00
Rob Bradford
92f3f86669 tests: Add integration test for power button
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-13 17:00:39 +00:00
Rob Bradford
f6d6495b93 resources: Add CONFIG_ACPI_BUTTON to linux-config-x86_64
Thise is needed to enable clean shutdown of the guest via an ACPI power
button.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-13 17:00:39 +00:00
Rob Bradford
68d90cbe65 opeenapi: Add power button API entry point
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-13 17:00:39 +00:00
Rob Bradford
d0b59ca3a0 ch-remote: Add support for "power-button"
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-13 17:00:39 +00:00
Rob Bradford
981bb72a09 vmm: api: Add "power-button" API entry point
This will lead to the triggering of an ACPI button inside the guest in
order to cleanly shutdown the guest.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-13 17:00:39 +00:00
Rob Bradford
843a010163 vmm: vm, device_manager: Trigger a power button notification via ACPI
Use the ACPI GED device to trigger a notitifcation of type
POWER_BUTTON_CHANGED which will ultimately lead to the guest being
notified.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-13 17:00:39 +00:00
Rob Bradford
c381b36b87 devices: acpi: Trigger the power button upon GED event
If a GED event of type 0x8 (for power button) is received notify the
guest OS that this button device has been activated.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-13 17:00:39 +00:00
Rob Bradford
ff4d378f1b vmm: device_manager: acpi: Add a power button (PNP0C0C)
Add a power button to the devices defined in the \_SB

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-13 17:00:39 +00:00
Rob Bradford
74a4aba257 devices: Add notification value for power button
Add a value to the ACPI notification type to indicate the power button
is to be triggered.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-13 17:00:39 +00:00
Rob Bradford
7b376fa8e0 devices: acpi: Generalise the HotPlugNotificationFlags
Renamed this bitfield as it will also be used for non-hotplug purposes
such as synthesising a power button.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-13 17:00:39 +00:00
Rob Bradford
23afe89089 virtio-devices: Derive thread names from device ids
In order to make the thread naming more useful derive their name from
the device id (which can be supplied by the user) and a device specific
suffix that has details of the individual queue (or queue pair.)

e.g.

rob@artemis:~$ pstree -p -c -l -t `pidof cloud-hypervisor`
cloud-hyperviso(27501)─┬─{_console}(27525)
                       ├─{_disk0_q0}(27529)
                       ├─{_disk0_q1}(27532)
                       ├─{_net1_ctrl}(27533)
                       ├─{_net1_qp0}(27534)
                       ├─{_net1_qp1}(27535)
                       ├─{_rng}(27526)
                       ├─{http-server}(27504)
                       ├─{seccomp_signal_}(27502)
                       ├─{signal_handler}(27523)
                       ├─{vcpu0}(27520)
                       ├─{vcpu1}(27522)
                       └─{vmm}(27503)

Fixes: #2077

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-13 16:56:44 +01:00
Sebastien Boeuf
3b43551d98 ci: Use device mapper to avoid copying Windows image
The Windows image is quite large (about 20GiB), hence it takes some time
to copy it for every test in order to avoid potential corruption.

One way to mitigate that without compromising on safety between each
test is by using device mapper. By creating a read-only base, we ensure
the image won't be modified by any of the tests, and by creating one
snapshot for each test, we avoid copying the entire image each time.
A dedicated Copy On Write disk image is created to handle any change
that might be performed on the base image, letting the tests behave as
expected.

Fixes #2155

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-13 10:48:06 +00:00
Sebastien Boeuf
c3df42d42f ci: Copy Windows image for each integration test
By relying on the Guest object, Windows dedicated tests copy the Windows
guest image before booting from it. The point being to avoid corruption
between multiple tests. This is already how the rest of the integration
tests work, Windows tests were the only ones missing this feature.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-13 10:48:06 +00:00
dependabot-preview[bot]
6b424b5f6b build(deps): bump rand from 0.8.1 to 0.8.2
Bumps [rand](https://github.com/rust-random/rand) from 0.8.1 to 0.8.2.
- [Release notes](https://github.com/rust-random/rand/releases)
- [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/rand/compare/0.8.1...0.8.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-13 10:41:29 +00:00
dependabot-preview[bot]
b2dd03b2dc build(deps): bump getrandom from 0.1.15 to 0.1.16
Bumps [getrandom](https://github.com/rust-random/getrandom) from 0.1.15 to 0.1.16.
- [Release notes](https://github.com/rust-random/getrandom/releases)
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/getrandom/compare/v0.1.15...v0.1.16)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-13 07:19:44 +00:00
dependabot-preview[bot]
4ebca7f4ea build(deps): bump thread_local from 1.0.1 to 1.1.0
Bumps [thread_local](https://github.com/Amanieu/thread_local-rs) from 1.0.1 to 1.1.0.
- [Release notes](https://github.com/Amanieu/thread_local-rs/releases)
- [Commits](https://github.com/Amanieu/thread_local-rs/compare/v1.0.1...v1.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-13 07:19:20 +00:00
Rob Bradford
d036210ecd build: deps: Bump serde and serde_derive together
The tight coupling of these packages caused issues for dependabot trying
to update them separately so instead combine them together into one
update.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-12 11:16:22 +01:00
Rob Bradford
39d080e0c1 main: Give a friendly message when we get a seccomp violation
If we receive SIGSYS and identify it as a seccomp violation then give
friendly instructions on how to debug further. We are unable to decode
the siginfo_t struct ourselves due to https://github.com/rust-lang/libc/issues/716

Fixes: #2139

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-12 09:23:29 +00:00
dependabot-preview[bot]
d83c9a74f4 build(deps): bump tempfile from 3.1.0 to 3.2.0
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.1.0 to 3.2.0.
- [Release notes](https://github.com/Stebalien/tempfile/releases)
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/NEWS)
- [Commits](https://github.com/Stebalien/tempfile/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-12 08:21:47 +00:00
dependabot-preview[bot]
d26866e018 build(deps): bump libc from 0.2.81 to 0.2.82
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.81 to 0.2.82.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.81...0.2.82)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-12 07:06:21 +00:00
Rob Bradford
ba7864e111 tests: Send systemd journal to console
This will aid debugging of test issues especially those for critical
services during the boot.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-11 16:38:07 +00:00
Rob Bradford
5881809126 tests: Update integration tests to use new image without pollinate
This image does not have the pollinate service which can sometimes fail
and prevent SSH from starting as it marks itself as a prerequisite. This
service will never fully succeed as it tries to make a network
connection which will fail inside our test VMs.

Fixes: #2113

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-11 16:38:07 +00:00
Rob Bradford
21ba34542d doc: Update documentation to note removal of pollinate package
Also update to include a simple version number in the image name.

See: #2113

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-11 16:38:07 +00:00
dependabot-preview[bot]
ab456affb3 build(deps): bump log from 0.4.11 to 0.4.13
Bumps [log](https://github.com/rust-lang/log) from 0.4.11 to 0.4.13.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.11...0.4.13)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-11 12:49:34 +00:00
Rob Bradford
852bf0b2ce scripts, resources: aarch64: Update to Linux kernel v5.10 base
This allows the removal of most of the custom patches in particular all
the virtio-fs ones have been integrated.

Fixes: #2070

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-11 12:56:05 +01:00
Rob Bradford
642a1a610f scripts: Update to Linux fork using latest virtio-iommu patches
The ch-5.10.6 branch is rebased on top of Linux stable and includes the
latest virtio-iommu support patches.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-11 12:56:05 +01:00
Rob Bradford
bdfe6a69ef virtio-devices: iommu: Update to latest version of IOMMU spec
This is order to support the latest patches from
https://jpbrucker.net/git/linux/commit/?h=virtio-iommu/devel&id=ddc3e6ce3f534af827a9c8f91e12a7082de8ec61

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-11 12:56:05 +01:00
Sebastien Boeuf
7889fc9207 scripts: Run test container with the default bridge network
Using --net=host is not necessary for any of the integration tests, so
let's use the default network option called "bridge".

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-11 11:18:48 +00:00
Rob Bradford
cb826aa2f1 vmm: seccomp: Add open() to vCPU permitted syscalls
Older libc (like RHEL7) uses open() rather than openat(). This was
demonstrated through a failure to open /etc/localtime as used by
gmtime() libc call trigged from the vCPU thread (CMOS device.)

Fixes: #2111

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-11 11:24:13 +01:00
Sebastien Boeuf
df522cf12c ci: Re-enable test_windows_guest_snapshot_restore
This reverts commit 72d054bf40.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-11 09:32:58 +00:00
Rob Bradford
a920ef48de Revert "tests: Temporarily disable test_watchdog on aarch64"
This reverts commit 49b49421d0.

Probable solution was applied in f70852c04b

Fixes: #2103

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-11 10:26:52 +01:00
dependabot-preview[bot]
9cd8aa1af9 build(deps): bump addr2line from 0.14.0 to 0.14.1
Bumps [addr2line](https://github.com/gimli-rs/addr2line) from 0.14.0 to 0.14.1.
- [Release notes](https://github.com/gimli-rs/addr2line/releases)
- [Changelog](https://github.com/gimli-rs/addr2line/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gimli-rs/addr2line/compare/0.14.0...0.14.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-11 08:09:26 +00:00
dependabot-preview[bot]
f6b63af06d build(deps): bump anyhow from 1.0.37 to 1.0.38
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.37 to 1.0.38.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.37...1.0.38)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-11 08:08:59 +00:00
dependabot-preview[bot]
8ff1142bf4 build(deps): bump signal-hook from 0.3.2 to 0.3.3
Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.3.2 to 0.3.3.
- [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/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-11 08:08:39 +00:00
dependabot-preview[bot]
5de4d03238 build(deps): bump regex from 1.4.2 to 1.4.3
Bumps [regex](https://github.com/rust-lang/regex) from 1.4.2 to 1.4.3.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.4.2...1.4.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-08 18:20:40 +00:00
dependabot-preview[bot]
302e4c17d2 build(deps): bump smallvec from 1.6.0 to 1.6.1
Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.6.0 to 1.6.1.
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/compare/v1.6.0...v1.6.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-08 18:17:57 +00:00
Sebastien Boeuf
b49c7dfd65 ci: Always download the Windows image
Because we're back on transient builder, let's download the image
everytime.

This reverts commit b5653d5278.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-08 17:18:28 +00:00
dependabot-preview[bot]
985da4d3fe build(deps): bump regex-syntax from 0.6.21 to 0.6.22
Bumps [regex-syntax](https://github.com/rust-lang/regex) from 0.6.21 to 0.6.22.
- [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)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-08 16:45:25 +00:00
dependabot-preview[bot]
2ec7d1ae05 build(deps): bump linux-loader from acf9c21 to 2855be1
Bumps [linux-loader](https://github.com/rust-vmm/linux-loader) from `acf9c21` to `2855be1`.
- [Release notes](https://github.com/rust-vmm/linux-loader/releases)
- [Commits](acf9c21591...2855be15a7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-08 16:29:48 +00:00
dependabot-preview[bot]
fc47dd6645 build(deps): bump thiserror from 1.0.22 to 1.0.23
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.22 to 1.0.23.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.22...1.0.23)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-08 16:01:10 +00:00
dependabot-preview[bot]
2e924f458e build(deps): bump syn from 1.0.57 to 1.0.58
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.57 to 1.0.58.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.57...1.0.58)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-08 15:33:20 +00:00
Sebastien Boeuf
20fde6b924 tests: Increase sleep time in Windows integration tests
Some sporadic failures were due to an early connection to the VM while
it was not fully ready. Increasing sleep times fixes these issues.

Fixes #2104

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-08 15:03:04 +00:00
Rob Bradford
72d054bf40 tests: Teporarily disable test_windows_guest_snapshot_restore
This test is reliably failing on our CI and we need time to investigate
why.

See: #2126

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-08 15:03:04 +00:00
Rob Bradford
e0d79196c8 virtio-devices, vmm: Enhance debugging around virtio device activation
Sometimes when running under the CI tests fail due to a barrier not
being released and the guest blocks on an MMIO write. Add further
debugging to try and identify the issue.

See: #2118

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-08 14:06:44 +00:00
Bo Chen
a286e960ed tests: Remove the check on the "booted" message in 'wait_vm_boot()'
Given we already check the connected IP address matches the expected
guest IP address, the check on the "booted" message is not needed.

Fixes: #2117

Signed-off-by: Bo Chen <chen.bo@intel.com>
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-08 12:54:35 +00:00
Sebastien Boeuf
f70852c04b virtio-devices: Update seccomp filters for virtio-net thread
On aarch64, the openat() syscall was missing from the seccomp filters
list, preventing the test_watchdog from running properly.

Fixes #2103

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-01-08 12:37:32 +00:00
Rob Bradford
8f740f5c02 Jenkinsfile: Disable fast failing
Temporarily disable fast failing to try and make progress on CI
stabilisation to allow more test coverage.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-08 12:24:33 +00:00
Rob Bradford
17c9e2cd4b tests: Make boot notifications retry
If the guest fails to communicate with the test harness then retry.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-08 12:24:33 +00:00
Rob Bradford
b5653d5278 Jenkinsfile: Don't download the Windows images
They are already provisioned on the builder machine.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-07 17:31:02 +00:00
Rob Bradford
28abe63f46 tests: Fix test_virtio_block_disable_io_uring()
This test wasn't actually disabling io_uring.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-06 18:26:02 +00:00
Rob Bradford
49b49421d0 tests: Temporarily disable test_watchdog on aarch64
This test is very flaky and regularly causing CI failures. Until we can
identify the root cause we should disable this test.

See: #2103

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-06 18:26:02 +00:00
Rob Bradford
ef12216c19 tests: Add explicit QCOW2 based image test
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-06 18:26:02 +00:00
Rob Bradford
e05ed9240a tests: Use raw images for all tests
Simplify our image handling by not copying both QCOW2 and raw images for
every test. Allow the test to choose QCOW2 or raw by specifying the
image name manually. A follow on patch will add explicity QCOW2 tests.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-06 18:26:02 +00:00
Rob Bradford
c91d25ea64 tests: Don't swallow SSH errors
When an SSH command fails we want to be able to see, via a panic() why
and where it failed. Replace use of .unwrap_or_default() from SSH
command calls to ensure that we can see the location of the panic.

Also enhance the existing SSH output code to show the error if there is
one.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-06 13:51:26 +01:00
Rob Bradford
315a730128 virtio-devices: net: Reduce debug level of EVENT_IDX messages
This logging is too spammy for info!() level and should be handled as
debug!() level

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-06 13:51:26 +01:00
Rob Bradford
230e8a23a0 vm-virtio: queue: Reduce logging level of EVENT_IDX logs
This logging is too spammy for info!() level and should be handled as
debug!() level

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-06 13:51:26 +01:00
Mikko Ylinen
f583aa9d30 sgx: update virt EPC device path and docs
Based on the LKML feedback, the devices under /dev/sgx/* are
not justified. SGX RFC v40 moves the SGX device nodes to /dev/sgx_*
and this is reflected in kvm-sgx (next branch) too.

Update cloud-hypervisor code and documentation to follow this.

Signed-off-by: Mikko Ylinen <mikko.ylinen@intel.com>
2021-01-05 15:48:17 +00:00
Rob Bradford
76adea46d0 Revert "build(deps): bump linux-loader from acf9c21 to b18d387"
This reverts commit 7f1f335950.

This breaks the compilation on Fedora/RedHat machines by requiring
dpkg-deb in the build.rs

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-05 15:43:40 +00:00
dependabot-preview[bot]
7f1f335950 build(deps): bump linux-loader from acf9c21 to b18d387
Bumps [linux-loader](https://github.com/rust-vmm/linux-loader) from `acf9c21` to `b18d387`.
- [Release notes](https://github.com/rust-vmm/linux-loader/releases)
- [Commits](acf9c21591...b18d387889)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-05 11:15:02 +00:00
dependabot-preview[bot]
2e6f93e1a9 build(deps): bump smallvec from 1.5.1 to 1.6.0
Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.5.1 to 1.6.0.
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/compare/v1.5.1...v1.6.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-05 07:02:07 +00:00
Rob Bradford
539708e45e scripts, resources: x86_64: Update to Linux kernel v5.10 base
This allows the removal of most of the custom patches in particular all
the virtio-fs ones have been integrated.

Partially fixes: #2070

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 22:44:40 +00:00
Rob Bradford
2e87d5ae02 tests: integration: Check different virtio-fs SHM region names
Depending on the kernel version the SHM region has a different name.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 22:44:40 +00:00
Rob Bradford
14af74cb5b vmm: seccomp: Allow clock_gettime() on the vCPU thread
If the vCPU thread calls log!() the time difference between the call
time and the boot up time is reported. On most environments and
architectures this covered by a vDSO call rather than a syscall. However
on some platforms this turns into a syscall.

Fixes: #2080

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 10:13:42 -08:00
dependabot-preview[bot]
73612401a5 build(deps): bump signal-hook from 0.2.2 to 0.3.2
Manually changed to reflect changes in mutability of signals and
rearrangement of constants.

Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.2.2 to 0.3.2.
- [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.2.2...v0.3.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 17:59:41 +00:00
dependabot-preview[bot]
858f64b3dc build(deps): bump rand from 0.8.0 to 0.8.1
Bumps [rand](https://github.com/rust-random/rand) from 0.8.0 to 0.8.1.
- [Release notes](https://github.com/rust-random/rand/releases)
- [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/rand/compare/0.8.0...0.8.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-04 16:36:19 +00:00
dependabot-preview[bot]
225bedcb20 build(deps): bump arc-swap from 1.1.0 to 1.2.0
Bumps [arc-swap](https://github.com/vorner/arc-swap) from 1.1.0 to 1.2.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/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-04 13:32:54 +00:00
dependabot-preview[bot]
8367784cf3 build(deps): bump syn from 1.0.56 to 1.0.57
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.56 to 1.0.57.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.56...1.0.57)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-04 13:32:17 +00:00
Rob Bradford
ecc1da95dd arch: aarch64: Remove unnecessary literal cast
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 13:46:37 +01:00
Rob Bradford
184baff355 hypervisor: kvm: aarch64: Use struct initialisation
error: field assignment outside of initializer for an instance created with Default::default()
Error:     --> hypervisor/src/kvm/mod.rs:1239:9
     |
1239 |         state.mp_state = self.get_mp_state()?;
     |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
     = note: `-D clippy::field-reassign-with-default` implied by `-D warnings`
note: consider initializing the variable with `kvm::aarch64::VcpuKvmState { mp_state: self.get_mp_state()?, ..Default::default() }` and removing relevant reassignments
    --> hypervisor/src/kvm/mod.rs:1237:9
     |
1237 |         let mut state = CpuState::default();
     |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#field_reassign_with_default

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 13:46:37 +01:00
Rob Bradford
3ad94ddf7c devices: rtc_pl031: Don't use manual range check
error: manual `Range::contains` implementation
Error:    --> devices/src/legacy/rtc_pl031.rs:342:12
    |
342 |         if offset < AMBA_ID_HIGH && offset >= AMBA_ID_LOW {
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `(AMBA_ID_LOW..AMBA_ID_HIGH).contains(&offset)`
    |
    = note: `-D clippy::manual-range-contains` implied by `-D warnings`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 13:46:37 +01:00
Rob Bradford
fabd63072b misc: Remove unnecessary literal casts
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 13:46:37 +01:00
Rob Bradford
05cdef17f4 virtio-devices: mem, balloon: Use struct initialisation
error: field assignment outside of initializer for an instance created with Default::default()
   --> virtio-devices/src/mem.rs:496:9
    |
496 |         resp.resp_type = resp_type;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
note: consider initializing the variable with `mem::VirtioMemResp { resp_type: resp_type, ..Default::default() }` and removing relevant reassignments
   --> virtio-devices/src/mem.rs:495:9
    |
495 |         let mut resp = VirtioMemResp::default();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#field_reassign_with_default

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 13:46:37 +01:00
Rob Bradford
6ccd32c904 pci: Remove manual range checks
error: manual `Range::contains` implementation
   --> pci/src/vfio.rs:948:12
    |
948 |         if (reg_idx >= PCI_CONFIG_BAR0_INDEX && reg_idx < PCI_CONFIG_BAR0_INDEX + BAR_NUMS)
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `(PCI_CONFIG_BAR0_INDEX..PCI_CONFIG_BAR0_INDEX + BAR_NUMS).contains(&reg_idx)`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 13:46:37 +01:00
Rob Bradford
50dae04c05 arch: smbios: Use literal types rather than casts
We must explicitly mark these values as u8 as the function that consumes
them takes a T and needs to use the specific width.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 13:46:37 +01:00
Rob Bradford
44ac11efc7 arch: smbios: Use struct initialiser where possible
Checking arch v0.1.0 (/home/rob/src/cloud-hypervisor/arch)
error: field assignment outside of initializer for an instance created with Default::default()
   --> arch/src/x86_64/smbios.rs:174:9
    |
174 |         smbios_biosinfo.typ = BIOS_INFORMATION;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::field-reassign-with-default` implied by `-D warnings`
note: consider initializing the variable with `x86_64::smbios::SmbiosBiosInfo { typ: BIOS_INFORMATION, length: mem::size_of::<SmbiosBiosInfo>() as u8, handle: handle, vendor: 1, version: 2, characteristics: PCI_SUPPORTED, characteristics_ext2: IS_VIRTUAL_MACHINE, ..Default::default() }` and removing relevant reassignments
   --> arch/src/x86_64/smbios.rs:173:9
    |
173 |         let mut smbios_biosinfo = SmbiosBiosInfo::default();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#field_reassign_with_default

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 13:46:37 +01:00
Rob Bradford
f452fe7497 hypervisor: kvm: Use struct initialiser where possible
error: field assignment outside of initializer for an instance created with Default::default()
   --> hypervisor/src/kvm/mod.rs:318:9
    |
318 |         cap.cap = KVM_CAP_SPLIT_IRQCHIP;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::field-reassign-with-default` implied by `-D warnings`
note: consider initializing the variable with `kvm_bindings::kvm_enable_cap { cap: KVM_CAP_SPLIT_IRQCHIP, ..Default::default() }` and removing relevant reassignments
   --> hypervisor/src/kvm/mod.rs:317:9
    |
317 |         let mut cap: kvm_enable_cap = Default::default();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#field_reassign_with_default

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 13:46:37 +01:00
Rob Bradford
a2e1e13918 vhost_user_block: Use struct instantiation rather than mut variable
error: field assignment outside of initializer for an instance created with Default::default()
   --> vhost_user_block/src/lib.rs:223:9
    |
223 |         config.capacity = nsectors;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::field-reassign-with-default` implied by `-D warnings`
note: consider initializing the variable with `block_util::VirtioBlockConfig { capacity: nsectors, blk_size: BLK_SIZE, size_max: 65535, seg_max: 128 - 2, min_io_size: 1, opt_io_size: 1, num_queues: num_queues as u16, writeback: 1, ..Default::default() }` and removing relevant reassignments
   --> vhost_user_block/src/lib.rs:221:9
    |
221 |         let mut config = VirtioBlockConfig::default();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#field_reassign_with_default

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 13:46:37 +01:00
Rob Bradford
a4134f6b25 net_util: Remove unit error from Result
error: this returns a `Result<_, ()>
  --> net_util/src/mac.rs:68:5
   |
68 |     pub fn from_bytes(src: &[u8]) -> Result<MacAddr, ()> {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `-D clippy::result-unit-err` implied by `-D warnings`
   = help: use a custom Error type instead
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#result_unit_err

Replace with std::io::Error like other locations in the same file.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 13:46:37 +01:00
Rob Bradford
d2de263774 qcow: Use .contains() for range check
error: manual `!RangeInclusive::contains` implementation
   --> qcow/src/qcow.rs:412:12
    |
412 |         if cluster_bits < MIN_CLUSTER_BITS || cluster_bits > MAX_CLUSTER_BITS {
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!(MIN_CLUSTER_BITS..=MAX_CLUSTER_BITS).contains(&cluster_bits)`
    |
    = note: `-D clippy::manual-range-contains` implied by `-D warnings`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 13:46:37 +01:00
Rob Bradford
9f2e7f455f block_util, vhost_user_block: Avoid unnecessary literal cast
error: casting integer literal to `u64` is unnecessary
  --> block_util/src/lib.rs:35:30
   |
35 | pub const SECTOR_SIZE: u64 = (0x01 as u64) << SECTOR_SHIFT;
   |                              ^^^^^^^^^^^^^ help: try: `0x01_u64`
   |
   = note: `-D clippy::unnecessary-cast` implied by `-D warnings`
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 13:46:37 +01:00
Rob Bradford
faba6a3fb3 vmm: memory_manager: Use workaround for conditional function arguments
With Rust 1.49 using attributes on a function parameter is not allowed.
The recommended workaround is to put it in a new block.

error[E0658]: attributes on expressions are experimental
   --> vmm/src/memory_manager.rs:698:17
    |
698 |                 #[cfg(target_arch = "x86_64")]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information

error: removing an expression is not supported in this position
   --> vmm/src/memory_manager.rs:698:17
    |
698 |                 #[cfg(target_arch = "x86_64")]
    |

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-01-04 13:46:37 +01:00
Wei Liu
2aaf0540b6 hypervisor: drop linux-loader dependency
It is not used anywhere inside the hypervisor crate.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-01-04 10:17:20 +00:00
dependabot-preview[bot]
d82e74e4bf build(deps): bump quote from 1.0.7 to 1.0.8
Bumps [quote](https://github.com/dtolnay/quote) from 1.0.7 to 1.0.8.
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.7...1.0.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-01 11:12:44 +00:00
dependabot-preview[bot]
f9a3476016 build(deps): bump serde_json from 1.0.60 to 1.0.61
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.60 to 1.0.61.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.60...v1.0.61)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-01 11:12:19 +00:00
dependabot-preview[bot]
aaa364a9c5 build(deps): bump openssl-sys from 0.9.59 to 0.9.60
Bumps [openssl-sys](https://github.com/sfackler/rust-openssl) from 0.9.59 to 0.9.60.
- [Release notes](https://github.com/sfackler/rust-openssl/releases)
- [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.59...openssl-sys-v0.9.60)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-30 07:54:34 +00:00
dependabot-preview[bot]
d20e07b271 build(deps): bump itoa from 0.4.6 to 0.4.7
Bumps [itoa](https://github.com/dtolnay/itoa) from 0.4.6 to 0.4.7.
- [Release notes](https://github.com/dtolnay/itoa/releases)
- [Commits](https://github.com/dtolnay/itoa/compare/0.4.6...0.4.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-30 07:54:24 +00:00
dependabot-preview[bot]
3074b178bd build(deps): bump rand from 0.7.3 to 0.8.0
Bumps [rand](https://github.com/rust-random/rand) from 0.7.3 to 0.8.0.
- [Release notes](https://github.com/rust-random/rand/releases)
- [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/rand/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-29 20:13:28 +00:00
dependabot-preview[bot]
4751a5949d build(deps): bump syn from 1.0.54 to 1.0.56
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.54 to 1.0.56.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.54...1.0.56)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-29 19:25:53 +00:00
dependabot-preview[bot]
25d567b6c6 build(deps): bump anyhow from 1.0.35 to 1.0.37
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.35 to 1.0.37.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.35...1.0.37)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-29 19:25:41 +00:00
Rob Bradford
bb1ef5f1b8 tests: integration: Remove quiet from kernel command line
It will be useful to see kernel output from our integration tests when
they fail.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-18 16:05:14 +00:00
Rob Bradford
d9e1eec47d tests: integration: Use direct kernel boot for most tests
The boot time for direct kernel boot based tests is significantly
quicker than booting via the firmware and stock kernel as it triggers a
reboot during the boot process due to the initrd handling.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-18 16:05:14 +00:00
Rob Bradford
a4c076bd09 tests: integration: Don't always have kernel serial output
When doing a direct kernel boot only have console=ttyS0 in the command
line if we are explicitly testing the serial output. The default
behaviour is `--serial null` so this output will not be visible but will
trigger a KVM exit for every byte which is very costly when running
under nested virtualization.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-18 16:05:14 +00:00
Rob Bradford
8a27735826 main: Add thread name to log output
If there is no thread then the name is reported as "anonymous".

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-18 16:05:14 +00:00
Rob Bradford
e8c72b1b01 virtio-devices: pci: Improve debugging for activation barriers
On the CI we are seeing issues with the activation barriers not being released:

cloud-hypervisor: 12.452434193s: INFO:vmm/src/vm.rs:413 -- Waiting for barrier
cloud-hypervisor: 12.452499794s: INFO:virtio-devices/src/block.rs:382 -- Changing cache mode to writeback
cloud-hypervisor: 12.452605195s: INFO:vmm/src/vm.rs:413 -- Waiting for barrier
cloud-hypervisor: 12.452684596s: INFO:virtio-devices/src/transport/pci_device.rs:671 -- Waiting for barrier
cloud-hypervisor: 12.452708196s: INFO:virtio-devices/src/transport/pci_device.rs:673 -- Barrier released
cloud-hypervisor: 12.452717596s: INFO:vmm/src/vm.rs:415 -- Barrier released

Add some debugging to try and identify the vause of this issue.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-18 16:05:14 +00:00
Rob Bradford
ee537d9bde docs: Add instructions for using MACVTAP for bridging
Now that we can support supplying an fd to the TAP device we can support
the MACVTAP and MACVLAN use cases.

Fixes: #872

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 22:51:30 +01:00
Rob Bradford
873c79a931 tests: Add test_tap_from_fd()
This test creates new TAP device, opens it and then passed the fd in via
--net fd=<fd>

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 22:51:30 +01:00
Rob Bradford
7a51be48c6 vmm: openapi: Add fd to NetConfig definition
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 22:51:30 +01:00
Rob Bradford
7f9cdf1183 vmm: device_manager: Create a virtio-net device from TAP fd
If a TAP fd is supplied then create an virtio-net device using that TAP
fd.

Fixes: #2052

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 22:51:30 +01:00
Rob Bradford
72e5ed3372 vmm: config: Extend NetConfig to include fd for tap device
Add an "fd=" parameter to allow specifying a TAP fd to use. Currently
only one fd for one queue pair is supported.

Fixes: #2052

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 22:51:30 +01:00
Rob Bradford
ca48f1c995 virtio-devices: net: Support creating a device from a TAP fd
Add support for creating virtio-net device from existing TAP fd.
Currently only a single fd and thus no-more than 2 queues (one pair) is
suppored.

Fixes: #2052

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 22:51:30 +01:00
Rob Bradford
444905071b vmm: seccomp: Permit TUNGETIFF through the filter
This is used to obtain the TAP device name.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 22:51:30 +01:00
Rob Bradford
385d734847 net_util: Add API for creating a Tap from an fd
Ultimately this will allow the creation of a virtio-net device that is
backed by a file descriptor.

This function ensures that the TAP device is correctly setup with
offloading and non-blocking.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 22:51:30 +01:00
Rob Bradford
16c2eebfd1 net_util: Extend Tap::open_named() to take flags
This allows us to open the named TAP device without O_CLOEXEC for an
integration test.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 22:51:30 +01:00
Samuel Ortiz
21dcac7721 hypervisor: Bump iced-x86 to 1.10.0
And fix related warnings: op_kind and op_register are being deprecated
as they might panic.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 18:58:34 +00:00
Rob Bradford
3ee56112cb tests: Bump boot default timeout
Starting the virtio device threads from the VMM thread has slowed down
the start of the VM when running on a highly contested system like the
CI.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 11:23:53 +00:00
Rob Bradford
03db48306b vmm: Activate virtio device from VMM thread
When a device is ready to be activated signal to the VMM thread via an
EventFd that there is a device to be activated. When the VMM receives a
notification on the EventFd that there is a device to be activated
notify the device manager to attempt to activate any devices that have
not been activated.

As a side effect the VMM thread will create the virtio device threads.

Fixes: #1863

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 11:23:53 +00:00
Rob Bradford
dee42ebb29 virtio-devices: pci_device: Split out device activation
This can then be used to activate the device from a separate thread.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 11:23:53 +00:00
Rob Bradford
7cc729c7d9 pci, virtio-devices: Extend barrier returning through PCI code
We need to be able to return the barrier from the code that prepares to
activate the virtio device. This triggered by a write to the
configuration fields stored in the PCI BAR. Since bars can be accessed
by both memory mapping and through PCI config I/O several prototypes
must be changed.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 11:23:53 +00:00
Rob Bradford
a8643dc523 vm-device, vmm: Wait for barrier if one is returned
Wait for the barrier if one is provided by the result of the MMIO and
PIO write.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 11:23:53 +00:00
Rob Bradford
1fc6d50f3e misc: Make Bus::write() return an Option<Arc<Barrier>>
This can be uses to indicate to the caller that it should wait on the
barrier before returning as there is some asynchronous activity
triggered by the write which requires the KVM exit to block until it's
completed.

This is useful for having vCPU thread wait for the VMM thread to proceed
to activate the virtio devices.

See #1863

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 11:23:53 +00:00
Rob Bradford
dbf4a252ad devices: acpi: Remove empty BusDevice::write implementation
The trait already includes an empty implementation of this function.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-17 11:23:53 +00:00
dependabot-preview[bot]
add9b13497 build(deps): bump signal-hook from 0.2.1 to 0.2.2
Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.2.1 to 0.2.2.
- [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.2.1...v0.2.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-15 18:03:49 +00:00
dependabot-preview[bot]
3d097eef44 build(deps): bump arc-swap from 1.0.0 to 1.1.0
Bumps [arc-swap](https://github.com/vorner/arc-swap) from 1.0.0 to 1.1.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.0.0...v1.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-14 09:13:04 +00:00
Muminul Islam
8c85dd32fa hypervisor: Move msr and msr_data macro to arch/x86
Currently these two macros(msr, msr_data) reside both on kvm and mshv
module. Definition is same for both module. Moving them to arch/x86
module eliminates redundancy and makes more sense.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-11 00:59:46 +01:00
Muminul Islam
aac86f4523 hypervisor: Fix clippy errors in the mshv module
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-10 19:43:58 +00:00
dependabot-preview[bot]
f3e889c204 build(deps): bump vcpkg from 0.2.10 to 0.2.11
Bumps [vcpkg](https://github.com/mcgoo/vcpkg-rs) from 0.2.10 to 0.2.11.
- [Release notes](https://github.com/mcgoo/vcpkg-rs/releases)
- [Changelog](https://github.com/mcgoo/vcpkg-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mcgoo/vcpkg-rs/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-10 19:19:55 +00:00
Rob Bradford
3eb9e61a32 rpm: Update spec file for version bump
Update the spec file for the rpm to the latest version.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-10 18:13:59 +00:00
Rob Bradford
d42b50845b build, release-notes.md: Document 0.12.0 release
Update release notes and version number for the new release.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-10 18:11:56 +00:00
Rob Bradford
06f391e022 tests: integration: Retry epoll if we receive -EINTR or -EAGAIN
On the CI we are seeing that sometimes the epoll is receiving these
errors which do not indicate a failure but that we should retry.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-10 10:11:19 -08:00
dependabot-preview[bot]
60d2469e7a build(deps): bump openssl-sys from 0.9.58 to 0.9.59
Bumps [openssl-sys](https://github.com/sfackler/rust-openssl) from 0.9.58 to 0.9.59.
- [Release notes](https://github.com/sfackler/rust-openssl/releases)
- [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.58...openssl-sys-v0.9.59)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-10 07:33:54 +00:00
Wei Liu
c4f8e4b000 main: provide a sensible error message when /dev/mshv is missing
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-12-09 17:28:36 +00:00
Muminul Islam
c32959261e gh: Expand clippy tests to cover the mshv feature
Since we can't test mshv and kvm at the same time, --all-features no
longer work.
We factorize all, non-hypervisor related features into a common set and
mix that with either mshv and kvm.

Co-Developed-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Co-Developed-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-09 14:55:20 +01:00
Muminul Islam
ef3fad8388 hypervisor: mshv: Implement CPU state for MshvVcpu
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-09 14:55:20 +01:00
Muminul Islam
2b42f6c835 hypervisor: mhsv: Implement CPU run loop
Handle CPU exits, adding instruction emulations.
Keep CPU specific data inside vmm for later use.

Co-Developed-by: Nuno Das Neves <nudasnev@microsoft.com>
Signed-off-by: Nuno Das Neves <nudasnev@microsoft.com>
Co-Developed-by: Praveen Paladugu <prapal@microsoft.com>
Signed-off-by: Praveen Paladugu <prapal@microsoft.com>
Co-Developed-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Co-Developed-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-09 14:55:20 +01:00
Muminul Islam
7acb5c6437 hypervisor, mshv: Define MshvEmulatorContext
This patch adds the definition and implementation
MshvEmulatorContext which is platform emulation for Hyper-V.

Co-Developed-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Co-Developed-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-09 14:55:20 +01:00
Muminul Islam
63f356b75b hypervisor: mhsv: Define software emulated TLB
A software emulated TLB. This is mostly used by
the instruction emulator to cache gva to gpa
translations passed from the hypervisor.

Co-Developed-by: Nuno Das Neves <nudasnev@microsoft.com>
Signed-off-by: Nuno Das Neves <nudasnev@microsoft.com>
Co-Developed-by: Praveen Paladugu <prapal@microsoft.com>
Signed-off-by: Praveen Paladugu <prapal@microsoft.com>
Co-Developed-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Co-Developed-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-09 14:55:20 +01:00
Muminul Islam
fd0ef6cfb5 hypervisor: mshv: Emulate IrqFd and IOEventFd for mshv module
We don't have IrqFd and IOEventFd support in the kernel for now.
So an emulation layer is needed. In the future, we will be adding this
support in the kernel.

Co-Developed-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-09 14:55:20 +01:00
Muminul Islam
286a23fbd4 hypervisor: mshv: Add vmmops to MshvVm struct
vmmops trait object is needed to get access some
of the upper level vmm functionalities i.e guest
memory access, IO read write etc.

Co-Developed-by: Praveen Paladugu <prapal@microsoft.com>
Signed-off-by: Praveen Paladugu <prapal@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-09 14:55:20 +01:00
Muminul Islam
3a93487b82 hypervisor: mshv: Add Microsoft Hypervisor specific data to Mshv{Vm,Vcpu}
Adding hv_state (hyperv state) to Vm and Vcpu struct for mshv.
This state is needed to keep some kernel data(for now hypercall page)
in the vmm.

Co-Developed-by: Praveen Paladugu <prapal@microsoft.com>
Signed-off-by: Praveen Paladugu <prapal@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-09 14:55:20 +01:00
Muminul Islam
23c46b162e hypervisor, vmm: Implement the mshv module and add mshv support in vmm
Implement hypervisor, Vm, Vcpu crate at a minimal
functionalities. Also adds the mshv feature gate,
separates out the functionalities between kvm and
mshv inside the vmm crate.

Co-Developed-by: Nuno Das Neves <nudasnev@microsoft.com>
Signed-off-by: Nuno Das Neves <nudasnev@microsoft.com>
Co-Developed-by: Praveen Paladugu <prapal@microsoft.com>
Signed-off-by: Praveen Paladugu <prapal@microsoft.com>
Co-Developed-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Co-Developed-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-09 14:55:20 +01:00
Muminul Islam
f4af668d76 hypervisor, vmm: Implement MsiInterruptOps for mshv
Co-Developed-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-09 14:55:20 +01:00
Muminul Islam
7fe5d276a3 hypervisor: mshv: Add x86_64 module
Add x86_64 specific definitions as we only plan
to support x86_64 for the moment.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-09 14:55:20 +01:00
Muminul Islam
e664fa386b hypervisor: Modify toml file to add mshv-{bindings, ioctls) crates
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-09 14:55:20 +01:00
Muminul Islam
9919dec1d9 hypervisor: Introduce mshv module in the hypervisor
This is the initial folder structure of the mshv module inside
the hypervisor crate. The aim of this module is to support Microsoft
Hyper-V as a supported Hypervisor.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-09 14:55:20 +01:00
Muminul Islam
9ce6c3b75c hypervisor, vmm: Feature guard KVM specific code
There are some code base and function which are purely KVM specific for
now and we don't have those supports in mshv at the moment but we have plan
for the future. We are doing a feature guard with KVM. For example, KVM has
mp_state, cpu clock support,  which we don't have for mshv. In order to build
those code we are making the code base for KVM specific compilation.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-09 14:55:20 +01:00
dependabot-preview[bot]
47f59409db build(deps): bump anyhow from 1.0.34 to 1.0.35
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.34 to 1.0.35.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.34...1.0.35)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-08 09:01:03 +00:00
dependabot-preview[bot]
b51f112629 build(deps): bump libc from 0.2.80 to 0.2.81
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.80 to 0.2.81.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.80...0.2.81)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-08 08:13:51 +00:00
dependabot-preview[bot]
d158fa8de2 build(deps): bump linux-loader from 3cf96c5 to acf9c21
Bumps [linux-loader](https://github.com/rust-vmm/linux-loader) from `3cf96c5` to `acf9c21`.
- [Release notes](https://github.com/rust-vmm/linux-loader/releases)
- [Commits](3cf96c53ed...acf9c21591)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-08 08:13:27 +00:00
dependabot-preview[bot]
c64de38140 build(deps): bump syn from 1.0.53 to 1.0.54
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.53 to 1.0.54.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.53...1.0.54)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-07 22:10:21 +00:00
Rob Bradford
9594ecec0d build: Only pull in iced-x86 for x86_64 builds
Fixes: #2024

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-07 17:42:42 +00:00
Anatol Belski
6c0c47a530 docs/windows.md: Add explicit note on how to start WinDbg
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2020-12-07 16:56:00 +00:00
Wei Liu
6d38612f6c hypervisor: x86: move RFLAGS bits to regs.rs
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-12-07 14:35:35 +01:00
Wei Liu
a44d96c9cc hypervisor: emulator: switch to use vec in MockVMM
The customized hashmap macro can't be lifted to common MockVMM code.
MockVMM only needs a collection to iterate over to get initial register
states. A vector is just as good as a hashmap.

Switch to use a vector to store initial register states. This allows us
to drop the hashmap macro everywhere.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-12-07 14:35:35 +01:00
Wei Liu
93b7dcac12 hypervisor: emulator: emulate CMP
Unfortunately Rust stable does not yet have inline ASM support the flag
calculation will have to be implemented in software.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-12-07 14:35:35 +01:00
Wei Liu
dd3844a892 hypervisor: emulator: drop imm_op macro
It is not needed anymore.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-12-07 14:35:35 +01:00
Wei Liu
0c3ef986fa hypervisor: emulator: rewrite MOV emulation with get/set_op
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-12-07 14:35:35 +01:00
Wei Liu
53c3b00fb0 hypervisor: emulator: introduce get/set_op
Provide two helpers to get and set operands. This reduces repetition.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-12-07 14:35:35 +01:00
Rob Bradford
03b824be0b build: Disable fast failing for build actions
nightly / beta are not required actions but if they fail then all other
builds will be cancelled and so prevent the PR from being cleared as
buildable.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-07 12:36:38 +00:00
dependabot-preview[bot]
558975aa51 build(deps): bump serde_derive from 1.0.117 to 1.0.118
Bumps [serde_derive](https://github.com/serde-rs/serde) from 1.0.117 to 1.0.118.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.117...v1.0.118)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-07 09:22:13 +00:00
dependabot-preview[bot]
d78b9bd287 build(deps): bump smallvec from 1.5.0 to 1.5.1
Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.5.0 to 1.5.1.
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/compare/v1.5.0...v1.5.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-07 09:08:31 +00:00
dependabot-preview[bot]
365d39ca2c build(deps): bump serde from 1.0.117 to 1.0.118
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.117 to 1.0.118.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.117...v1.0.118)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-07 08:36:52 +00:00
Muminul Islam
d79594aa3f scripts: dev_cli: Remove unnecessary spaces
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-05 00:01:41 +01:00
Muminul Islam
27b5f8d7e3 scripts: Add an option to accept hypervisor argument
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-12-05 00:01:41 +01:00
Rob Bradford
2cc312b65c build: Fix cargo fuzz build
Unfortunately it seems patch entries are ignored when obtaining
dependencies from another workspace.

Remove the problematic kvm-ioctls and kvm-bindings patch entries and use
the forked repository directly.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-04 11:38:44 +00:00
dependabot-preview[bot]
d416271457 build(deps): bump cc from 1.0.65 to 1.0.66
Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.65 to 1.0.66.
- [Release notes](https://github.com/alexcrichton/cc-rs/releases)
- [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.65...1.0.66)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-04 10:51:49 +00:00
Rob Bradford
9e6a023f7f vmm: Don't continue to lookup debug I/O port
When using an PIO write to 0x80 which is a special case handle that and
then return without going through the resolve.

This removes an extra warning that is reported.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-03 07:25:42 -08:00
Wei Liu
90ae4676c8 hypervisor: x86: emulator: drop unneeded curly brackets
There is no need to have a pair of curly brackets for structures without
any member.

No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-12-03 14:52:00 +01:00
dependabot-preview[bot]
89bc413add build(deps): bump serde_json from 1.0.59 to 1.0.60
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.59 to 1.0.60.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.59...v1.0.60)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-03 13:50:29 +00:00
Wei Liu
c352b59857 hypervisor: emulator: drop InstructionMap
It is not needed anymore.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-12-02 19:45:36 +01:00
Wei Liu
ab89b48143 hypervisor: emulator: use static mapping to dispatch emulation
The mapping between code and its handler is static. We can drop the
HashMap in favour of a static match expression.

This has two benefits:
1. No more memory allocation and deallocation for the HashMap.
2. Shorter look-up time.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-12-02 19:45:36 +01:00
Rob Bradford
ffaab46934 misc: Use a more relaxed memory model when possible
When a total ordering between multiple atomic variables is not required
then use Ordering::Acquire with atomic loads and Ordering::Release with
atomic stores.

This will improve performance as this does not require a memory fence
on x86_64 which Ordering::SeqCst will use.

Add a comment to the code in the vCPU handling code where it operates on
multiple atomics to explain why Ordering::SeqCst is required.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-02 19:04:30 +01:00
Rob Bradford
280d4fb245 vmm: Include device tree in vm.info API
The DeviceNode cannot be fully represented as it embeds a Rust style
enum (i.e. with data) which is instead represented by a simple
associative array.

Fixes: #1167

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-01 16:44:25 +01:00
Samuel Ortiz
15f0451c34 hypervisor: emulator: Format instructions on error paths
Formatting instructions might be costly, so we only want to do that on
the emulation error paths.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-12-01 11:13:54 +01:00
Samuel Ortiz
3fa6e17cc4 hypervisor: x86: Make imm_op available to all emulated instructions
By moving it to the instructions root module.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-12-01 11:13:54 +01:00
Wei Liu
e2c81f9ed8 hypervisor: x86: Extend the imm_op() macro
To support every kind of immediate operands.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-12-01 11:13:54 +01:00
Rob Bradford
ead8453120 build: Remove vhost_user_fs
This has been superseded by virtiofsd-rs.

Fixes: #2013

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-01 11:13:21 +01:00
Rob Bradford
c4ebe83576 rpm: Update .spec file to not reference vhost_user_fs
Fixes: #2013

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-01 11:13:21 +01:00
Rob Bradford
1908f488c3 tests: Move tests from vhost_user_fs to virtiofsd-rs
Download and build virtiofsd-rs and then use that in the integration
test suite.

Fixes: #2013

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-01 11:13:21 +01:00
Rob Bradford
593a958fe5 pci, vmm: Include VFIO devices in device tree
Fixes: #1687

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-12-01 10:49:04 +01:00
Wei Liu
ba71390d6a hypervisor: drop arc-swap dependency
It is no longer needed after 0fec32658.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-11-30 16:47:32 +00:00
Samuel Ortiz
f6892f2ede hypervisor: emulator: Add a negative instruction fetch unit test
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-30 13:09:19 +00:00
Samuel Ortiz
251434862f hypervisor: emulator: Fix logic bug in MockVMM
emulate_first_insn() really means we want only the first instruction to
be emulated.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-30 13:09:19 +00:00
Samuel Ortiz
1ac4c42a84 hypervisor: emulator: Add initial fetch support
When the x86 instruction decoder tells us about some missing bytes from
the instruction stream, we call into the platform fetch method and
emulate one last instruction.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-30 13:09:19 +00:00
Samuel Ortiz
7dc92d1dac hypervisor: emulator: Decoding loop restructuring
In preparation for the instruction fetching step, we modify the decoding
loop so that we can check what the last decoding error is.

We also switch to explictly using decode_out() which removes a 32 bytes
copy compared to decode().

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-30 13:09:19 +00:00
Samuel Ortiz
7a4edecd29 hypervisor: x86: Add an address linearization method to CpuStateManager
From a CPU state and a segment, we can translate a logical (segmented)
address into a linear one.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-30 13:09:19 +00:00
Samuel Ortiz
d419e30df1 hypervisor: x86: Add a SegmentRegistorOps trait
In order to validate emulated memory accesses, we need to be able to get
all the segments descriptor attributes.

This is done by abstracting the SegmentRegister attributes through a
trait that each hypervisor will have to implement.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-30 13:09:19 +00:00
Samuel Ortiz
3faffcb087 hypervisor: emulator: Add a CPU mode getter to CpuStateManager
We need to be able to build the CPU mode from its state in order to
start implementing mode related checks in the x86 emulator.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-30 13:09:19 +00:00
Samuel Ortiz
b3a1f5f1be hypervisor: Start moving register definitions to the hypervisor crate
Most of arch/src/x86_64/regs.rs will eventually move unde
hypervisor/src/x86/regs.rs.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-30 13:09:19 +00:00
dependabot-preview[bot]
2bc5119730 build(deps): bump syn from 1.0.52 to 1.0.53
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.52 to 1.0.53.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.52...1.0.53)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-30 09:09:26 +00:00
dependabot-preview[bot]
5100bc94cc build(deps): bump syn from 1.0.51 to 1.0.52
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.51 to 1.0.52.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.51...1.0.52)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-28 00:28:08 +00:00
dependabot-preview[bot]
6bf9fe487b build(deps): bump pnet from 0.26.0 to 0.27.2
Bumps [pnet](https://github.com/libpnet/libpnet) from 0.26.0 to 0.27.2.
- [Release notes](https://github.com/libpnet/libpnet/releases)
- [Commits](https://github.com/libpnet/libpnet/compare/v0.26.0...v0.27.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-27 23:56:02 +00:00
Rob Bradford
d1a23d9085 docs: Add instructions for using perf
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-27 19:19:14 +01:00
Rob Bradford
05f785fa88 build: Move timeouts to integration test blocks
If we rely on timeouts at the top level we can get builds being aborted
simply because they took too long to be scheduled rather than because
the actual integration tests took too long.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-27 19:18:39 +01:00
Samuel Ortiz
a3d957ba4d hypervisor: emulator: Clean the MockVMM initialization path
Separate the standalone _init_and_run() function into 2 MockVMM methods:
new() and emulate_insn().

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-27 19:17:35 +01:00
Samuel Ortiz
5bd63efa45 hypervisor: emulator: Move MockVMM into a shared test module
The MockVMM platform will be used by other instructions emulation
implementations, but also by the emulator framework.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-27 19:17:35 +01:00
Wei Liu
66b001665f hypervisor: x86: only calculate address when necessary in MOV emulation
Only calculate the address when the operand is memory.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-11-26 16:12:23 +01:00
Wei Liu
c6aea5af5d hypervisor: x86: drop an extraneous box indirection
There is no need to put a box into another box.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-11-26 12:02:47 +00:00
Wei Liu
c8b655490e hypervisor: x86: reference PlatformEmulator in Emulator
The observation here is PlatformEmulator can be seen as the context for
emulation to take place. It should be rather easy to construct a context
that satisfies the lifetime constraints for instruction emulation.

The thread doing the emulation will have full ownership over the
context, so this removes the need to wrap PlatformEmulator in Arc and
Mutex, as well as the need for the context to be either Clone or Copy.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-11-26 12:14:40 +01:00
Rob Bradford
72741c557a actions: Add "--all --tests" to clippy in quality action
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-26 09:32:46 +01:00
Rob Bradford
b2608ca285 vmm: cpu: Fix clippy issues inside test
Found by:  cargo clippy --all-features --all --tests

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-26 09:32:46 +01:00
Rob Bradford
74fe032827 vm-device: bus: Fix clippy issues inside tests
Found by:  cargo clippy --all-features --all --tests

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-26 09:32:46 +01:00
Rob Bradford
40a2e3b462 vhost_user_block: Fix clippy issue
Found by:  cargo clippy --all-features --all --tests

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-26 09:32:46 +01:00
Rob Bradford
abc6672f21 qcow: Fix clippy issues inside tests
Found by:  cargo clippy --all-features --all --tests

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-26 09:32:46 +01:00
Rob Bradford
053c9e4d73 devices: serial: Fix clippy issues inside tests
Found by:  cargo clippy --all-features --all --tests

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-26 09:32:46 +01:00
Rob Bradford
9ea19852b5 arch: x86_64: Fix clippy issues inside tests
Found by:  cargo clippy --all-features --all --tests

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-26 09:32:46 +01:00
Rob Bradford
9871ff454b arch_gen: mpspec: Fix clippy issues inside tests
Found by:  cargo clippy --all-features --all --tests

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-26 09:32:46 +01:00
dependabot-preview[bot]
e817b4f36c build(deps): bump crossbeam-utils from 0.8.0 to 0.8.1
Bumps [crossbeam-utils](https://github.com/crossbeam-rs/crossbeam) from 0.8.0 to 0.8.1.
- [Release notes](https://github.com/crossbeam-rs/crossbeam/releases)
- [Changelog](https://github.com/crossbeam-rs/crossbeam/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-utils-0.8.0...crossbeam-utils-0.8.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-26 08:32:02 +00:00
Rob Bradford
6f63cd00eb vmm: device_manager: Remove ActivatedBackend struct
This was used for vhost-user self spawning but no longer has any users.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-25 20:47:43 +01:00
Wei Liu
a6ad85dc40 hypervisor: x86: handle more registers in emulator
List all GPRs documented in Intel's SDM.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-11-25 20:18:40 +01:00
Samuel Ortiz
0f4f30dbde hypervisor: x86: Add MOV to the emulator instruction map
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-25 17:02:11 +01:00
Samuel Ortiz
fe5401223b hypervisor: x86: Emulate MOV
And add a few unit tests based on a Mock platform.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-25 17:02:11 +01:00
Samuel Ortiz
12b7a498d9 hypervisor: x86: Add an instruction emulator
The emulator gets a CPU state from a CpuStateManager instance, emulates
the passed instructions stream and returns the modified CPU state.

The emulator is a skeleton for now since it comes with an empty
instruction mnemonic map.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-25 17:02:11 +01:00
Samuel Ortiz
1fc97e91a4 hypervisor: x86: Add an InstructionHandler interface
And an InstructionMap helper structure to map x86 mnemonic codes
to instruction handlers.

Any instruction emulation implementation should then boil down with
implementing InstructionHandler for any supported mnemonic.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-25 17:02:11 +01:00
Samuel Ortiz
fc5d6c96be hypervisor: x86: Add a minimal CpuStateManager implementation
Minimal will be defined by the amount of emulated instructions.
Carrying all GPRs, all CRs, segment registers and table registers should
cover quite a few instructions.

Co-developed-by: Wei Liu <liuwe@microsoft.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-25 17:02:11 +01:00
Samuel Ortiz
546778ebfb hypervisor: x86: Add a CpuStateManager interface
For efficiently emulating x86 instructions, we need to build and pass a
CPU state copy/reference to instruction emulation handlers. Those handlers
will typically modify the CPU state and let the caller commit those
changes back through the PlatformEmulator trait set_cpu_state method.

Hypervisors typically have internal CPU state structures, that maps back
to the correspinding kernel APIs. By implementing the CpuState trait,
instruction emulators will be able to directly work on CPU state
instances that are directly consumable by the underlying hypervisor and
its kernel APIs.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-25 17:02:11 +01:00
Samuel Ortiz
f0360aff83 hypervisor: Architecture agnostic instruction emulation interface
In order to emulate instructions, we need a way to get access to some of
the guest resources. The PlatformEmulator interface provides guest
memory and CPU state access to emulator implementations.

Typically, an hypervisor will implement PlatformEmulator for architecture
specific instruction emulators to build their framework on top of.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-25 17:02:11 +01:00
Samuel Ortiz
ae96aeda65 arch: Move the gdt module to the hypervisor crate
We will need the GDT API for the hypervisor's x86 instruction
emulator implementation, it's better if the arch crate depends on the
hypervisor one rather than the other way around.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-25 17:02:11 +01:00
Rob Bradford
b5b97f7b05 vmm: When receiving a migration store the config
The configuration is stored separately to the Vm in the VMM. The failure
to store the config was preventing the VM from shutting down correctly
as Vmm::vm_delete() checks for the presence of the config.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-25 01:27:26 +01:00
Rob Bradford
9fc2613b41 vm-device: bus: Remove unwrap() when upgrading weak reference
Rather return the None to the caller to handle instead. This removes the
source of a potential panic.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-25 01:27:26 +01:00
Rob Bradford
44b5a19209 bin: ch-remote: Fix typo in error message
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-25 01:27:26 +01:00
Rob Bradford
df6b52924f vmm: Unlink created socket after source connects
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-25 01:27:26 +01:00
Rob Bradford
1ab1341775 vmm: seccomp_filters: Add KVM_GET_DIRTY_LOG to permitted calls
The live migration support added use of this ioctl but it wasn't
included in the permitted list.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-25 01:27:26 +01:00
dependabot-preview[bot]
a29f7ffcc7 build(deps): bump signal-hook from 0.2.0 to 0.2.1
Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.2.0 to 0.2.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/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-25 00:26:27 +00:00
dependabot-preview[bot]
eda39d0469 build(deps): bump rust-argon2 from 0.8.2 to 0.8.3
Bumps [rust-argon2](https://github.com/sru-systems/rust-argon2) from 0.8.2 to 0.8.3.
- [Release notes](https://github.com/sru-systems/rust-argon2/releases)
- [Changelog](https://github.com/sru-systems/rust-argon2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sru-systems/rust-argon2/compare/0.8.2...0.8.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-24 09:38:49 +00:00
dependabot-preview[bot]
de0c24810e build(deps): bump syn from 1.0.50 to 1.0.51
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.50 to 1.0.51.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.50...1.0.51)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-24 06:01:35 +00:00
Samuel Ortiz
fadeb98c67 cargo: Bulk update
Includes updates for ssh2, cc, syn, tinyvec, backtrace micro-http and libssh2.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-23 12:25:31 +01:00
Samuel Ortiz
1fc0b94fcd cargo: Move to crates.io vm-memory 0.4.0
vm-memory 0.4.0 now contains all our fixes.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-23 10:55:13 +01:00
Samuel Ortiz
ef4c896bbf arch: aarch64: Fix rust 1.48 clippy warnings
methods called `new` usually return `Self`
See https://rust-lang.github.io/rust-clippy/master/index.html#new_ret_no_self

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-20 17:09:28 +01:00
Samuel Ortiz
72bb255ff6 pci, virtio-devices: Fix rust 1.48 clippy warnings
Unnecessary closure used to substitute value for `Option::None`
See https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-20 17:09:28 +01:00
Samuel Ortiz
a406d90059 arch: Fix rust 1.48 clippy warnings
const should not be mutable types:
https://rust-lang.github.io/rust-clippy/master/index.html#declare_interior_mutable_const

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-11-20 17:09:28 +01:00
dependabot-preview[bot]
0dfffee6ba build(deps): bump cc from 1.0.62 to 1.0.63
Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.62 to 1.0.63.
- [Release notes](https://github.com/alexcrichton/cc-rs/releases)
- [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.62...1.0.63)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-18 23:37:01 +00:00
Rob Bradford
0fec326582 hypervisor, vmm: Remove shared ownership of VmmOps
This interface is used by the vCPU thread to delegate responsibility for
handling MMIO/PIO operations and to support different approaches than a
VM exit.

During profiling I found that we were spending 13.75% of the boot CPU
uage acquiring access to the object holding the VmmOps via
ArcSwap::load_full()

    13.75%     6.02%  vcpu0            cloud-hypervisor    [.] arc_swap::ArcSwapAny<T,S>::load_full
            |
            ---arc_swap::ArcSwapAny<T,S>::load_full
               |
                --13.43%--<hypervisor::kvm::KvmVcpu as hypervisor::cpu::Vcpu>::run
                          std::sys_common::backtrace::__rust_begin_short_backtrace
                          core::ops::function::FnOnce::call_once{{vtable-shim}}
                          std::sys::unix::thread::Thread::new::thread_start

However since the object implementing VmmOps does not need to be mutable
and it is only used from the vCPU side we can change the ownership to
being a simple Arc<> that is passed in when calling create_vcpu().

This completely removes the above CPU usage from subsequent profiles.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-19 00:16:02 +01:00
dependabot-preview[bot]
6a591ca81d build(deps): bump pin-project from 1.0.1 to 1.0.2
Bumps [pin-project](https://github.com/taiki-e/pin-project) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/taiki-e/pin-project/releases)
- [Changelog](https://github.com/taiki-e/pin-project/blob/master/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project/compare/v1.0.1...v1.0.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-18 22:15:58 +00:00
dependabot-preview[bot]
a525f8365f build(deps): bump unicode-normalization from 0.1.15 to 0.1.16
Bumps [unicode-normalization](https://github.com/unicode-rs/unicode-normalization) from 0.1.15 to 0.1.16.
- [Release notes](https://github.com/unicode-rs/unicode-normalization/releases)
- [Commits](https://github.com/unicode-rs/unicode-normalization/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-18 22:15:49 +00:00
Rob Bradford
f271378811 tests: Wait for reboot in test_virtio_watchdog()
Aim to reduce flaky failures of this test by waiting for the VM to come
back after a reboot.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-18 18:27:34 +01:00
Rob Bradford
78b9edf848 tests: Get output from firmware and Linux for test_large_vm()
As we switched to focal for this test we no longer get any output during
the boot unless serial is used over virtio-console.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-18 18:27:34 +01:00
Rob Bradford
d0aebfb922 tests: Increase time waited for hotplugged memory to appear
There have been a lot of flakes around tests such as
test_virtio_fs_hotplug_dax_on_w_vhost_user_fs_daemon() or
test_virtio_fs_hotplug_dax_on() which all try and hotplug memory.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-18 18:27:34 +01:00
Rob Bradford
f913dd6150 tests: Add integration test to force io_uring off for block
Fixes: #1561

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-18 11:47:54 +01:00
Rob Bradford
c622278030 config, device_manager: Add support for disabling io_uring for testing
Add config parameter to --disk called "_disable_io_uring" (the
underscore prefix indicating it is not for public consumpion.) Use this
option to disable io_uring if it would otherwise be used.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-18 11:47:54 +01:00
Rob Bradford
d1d0421103 main: Remove --net-backend and --block-backend from cloud-hypervisor
Remove the parameters used for self spawning from the cloud-hypervisor
binary.

See: #1925

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-18 11:46:32 +01:00
Rob Bradford
fb70baece0 tests: Make integration test use vhost_user_{net,block} binaries
With the removal of vhost-user self-spawning support we should migrate
the tests to use the binaries so that we can remove the functionality
from the cloud-hypervisor binary itself.

See: #1925

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-18 11:46:32 +01:00
dependabot-preview[bot]
0159ab93e1 build(deps): bump unicode-normalization from 0.1.14 to 0.1.15
Bumps [unicode-normalization](https://github.com/unicode-rs/unicode-normalization) from 0.1.14 to 0.1.15.
- [Release notes](https://github.com/unicode-rs/unicode-normalization/releases)
- [Commits](https://github.com/unicode-rs/unicode-normalization/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-18 09:01:29 +00:00
dependabot-preview[bot]
609d704168 build(deps): bump smallvec from 1.4.2 to 1.5.0
Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.4.2 to 1.5.0.
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/compare/v1.4.2...v1.5.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-17 21:56:51 +00:00
Rob Bradford
3ac9b6c404 vmm: Implement live migration
Now the VM is paused/resumed by the migration process itself.

0. The guest configuration is sent to the destination
1. Dirty page log tracking is started by start_memory_dirty_log()
2. All guest memory is sent to the destination
3. Up to 5 attempts are made to send the dirty guest memory to the
   destination...
4. ...before the VM is paused
5. One last set of dirty pages is sent to the destination
6. The guest is snapshotted and sent to the destination
7. When the migration is completed the destination unpauses the received
   VM.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-17 16:57:11 +00:00
Rob Bradford
b34703d29f vmm: vm: Add dirty log related passthrough methods
This allows code running in the VMM to access the VM's MemoryManager's
functionality for managing the dirty log including resetting it but also
generating a table.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-17 16:57:11 +00:00
Rob Bradford
cf6763dfdb vmm: migration: Add missing response check
A read and check of the response was missing from when sending the
memory to the destination.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-17 16:57:11 +00:00
Rob Bradford
11a69450ba vm-migration, vmm: Send configuration in separate step
Prior to sending the memory the full state is not needed only the
configuration. This is sufficient to create the appropriate structures
in the guest and have the memory allocations ready for filling.

Update the protocol documentation to add a separate config step and move
the state to after the memory is transferred. As the VM is created in a
separate step to restoring it the requires a slightly different
constructor as well as saving the VM object for the subsequent commands.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-17 16:57:11 +00:00
Rob Bradford
c62e409827 memory_manager: Generate a MemoryRangeTable for dirty ranges
In order to do this we must extend the MemoryManager API to add the
ability to specify the tracking of the dirty pages when creating the
userspace mappings and also keep track of the userspace mappings that
have been created for RAM regions.

Currently the dirty pages are collected into ranges based on a block
level of 64 pages. The algorithm could be tweaked to create smaller
ranges but for now if any page in the block of 64 is dirty the whole
block is added to the range.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-17 16:57:11 +00:00
Rob Bradford
041724a7cf hypervisor: Add ability to get dirty logged pages
Return a bitmap of pages that have been dirtied (written to) since it
was last called.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-17 16:57:11 +00:00
Rob Bradford
8baa244ec1 hypervisor: Add control for dirty page logging
When creating a userspace mapping provide a control for enabling the
logging of dirty pages.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-17 16:57:11 +00:00
Anatol Belski
b399287430 memory_manager: Make addressable space size 64k aligned
While the addressable space size reduction of 4k in necessary due to
the Linux bug, the 64k alignment of the addressable space size is
required by Windows. This patch satisfies both.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2020-11-16 16:39:11 +00:00
Rob Bradford
c0827e01b1 build: Update arc-swap dependency to 1.0.0
Also bump the vm-memory version to one that depends on arc-swap 1.0.0
too.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-16 14:10:09 +01:00
Rob Bradford
46e736973e hypervisor: kvm: Correctly share VmmOps between Kvm{Vm,Vcpu}
Cloning the ArcSwapOption (like the ArcSwap) does not act like a
.clone() on an Arc, instead an entirely new ArcSwap is created with the
same contents. To correctly share the ArcSwap needs to be placed inside
an Arc.

See: 2433d5719b (diff-6c6d94533c44c19bd1416ef17bad1a878e63dca6e98d59181228fbe8f967c62bR6)

Due to this being wrongly used ::clone() was removed from
ArcSwap/ArcSwapOption in 1.0.0.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-16 14:10:09 +01:00
dependabot-preview[bot]
096d99664d build(deps): bump ssh2 from 0.8.2 to 0.8.3
Bumps [ssh2](https://github.com/alexcrichton/ssh2-rs) from 0.8.2 to 0.8.3.
- [Release notes](https://github.com/alexcrichton/ssh2-rs/releases)
- [Commits](https://github.com/alexcrichton/ssh2-rs/compare/0.8.2...0.8.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-15 16:01:54 +00:00
dependabot-preview[bot]
f7c42dc7d2 build(deps): bump vmm-sys-util from 0.6.1 to 0.7.0
Bumps [vmm-sys-util](https://github.com/rust-vmm/vmm-sys-util) from 0.6.1 to 0.7.0.
- [Release notes](https://github.com/rust-vmm/vmm-sys-util/releases)
- [Changelog](https://github.com/rust-vmm/vmm-sys-util/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-vmm/vmm-sys-util/compare/v0.6.1...v0.7.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-13 15:55:05 +00:00
dependabot-preview[bot]
37f947d614 build(deps): bump unicode-normalization from 0.1.13 to 0.1.14
Bumps [unicode-normalization](https://github.com/unicode-rs/unicode-normalization) from 0.1.13 to 0.1.14.
- [Release notes](https://github.com/unicode-rs/unicode-normalization/releases)
- [Commits](https://github.com/unicode-rs/unicode-normalization/compare/v0.1.13...v0.1.14)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-12 16:18:48 +00:00
dependabot-preview[bot]
47d2421e39 build(deps): bump once_cell from 1.5.1 to 1.5.2
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.5.1 to 1.5.2.
- [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.5.1...v1.5.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-12 14:02:38 +00:00
dependabot-preview[bot]
04419065a3 build(deps): bump once_cell from 1.5.0 to 1.5.1
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.5.0 to 1.5.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.5.0...v1.5.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-11 11:19:21 +00:00
Rob Bradford
ca60adda70 vmm: Add support for sending and receiving migration if VM is paused
This is tested by:

Source VMM:

target/debug/cloud-hypervisor --kernel ~/src/linux/vmlinux \
--pmem file=~/workloads/focal.raw --cpus boot=1 \
--memory size=2048M \
--cmdline"root=/dev/pmem0p1 console=ttyS0" --serial tty --console off \
--api-socket=/tmp/api1 -v

Destination VMM:

target/debug/cloud-hypervisor --api-socket=/tmp/api2 -v

And the following commands:

target/debug/ch-remote --api-socket=/tmp/api1 pause
target/debug/ch-remote --api-socket=/tmp/api2 receive-migration unix:/tmp/foo &
target/debug/ch-remote --api-socket=/tmp/api1 send-migration unix:/tmp/foo
target/debug/ch-remote --api-socket=/tmp/api2 resume

The VM is then responsive on the destination VMM.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-11 11:07:24 +01:00
Rob Bradford
dfe2dadb3e vmm: memory_manager: Make the snapshot source directory an Option
This allows the code to be reused when creating the VM from a snapshot
when doing VM migration.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-11 11:07:24 +01:00
Rob Bradford
523029449e bin: ch-remote: Add support for receive/send migration commands
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-11 11:07:24 +01:00
Rob Bradford
7ac764518c vmm: api: Implement API support for migration
Add API entry points with stub implementation for sending and receiving
a VM from one VMM to another.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-11 11:07:24 +01:00
Rob Bradford
aa98589bb4 vm-migration: Add protocol documentation and data structures
Add the documentation and basic implementation for supporting migration.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-11 11:07:24 +01:00
dependabot-preview[bot]
ca5f1d6de8 build(deps): bump once_cell from 1.4.1 to 1.5.0
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.4.1 to 1.5.0.
- [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.4.1...v1.5.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-11 08:47:02 +00:00
Julio Montes
270631922d vmm: openapi: remove omitempty json tag
Due to a known limitation in OpenAPITools/openapi-generator tool,
it's impossible to send go zero types, like false and 0 to
cloud-hypervisor because `omitempty` is added if a field is not
required.
Set cache_size, dax, num_queues and queue_size as required to remove
`omitempty` from the json tag.

fixes #1961

Signed-off-by: Julio Montes <julio.montes@intel.com>
2020-11-10 19:09:17 +01:00
Muminul Islam
465ef3f7ad scripts: dev_cli: Export volumes for windows test as well
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-11-09 14:58:26 -08:00
dependabot-preview[bot]
50e0423304 build(deps): bump futures from 0.3.7 to 0.3.8
Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.7 to 0.3.8.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.7...0.3.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-09 21:50:00 +00:00
Anatol Belski
906a1eb18d doc: Add notes to compile OVMF with legacy support
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2020-11-09 17:41:03 +01:00
Rob Bradford
7b77f1ef90 vmm: Remove self-spawning functionality for vhost-user-{net,block}
This also removes the need to lookup up the "exe" symlink for finding
the VMM executable path.

Fixes: #1925

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-09 00:16:15 +01:00
Rob Bradford
0005d11e32 vmm: config: Require a socket when using vhost-user
With self-spawning being removed both parameters are now required.

Fixes: #1925

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-09 00:16:15 +01:00
Rob Bradford
ec84abc5c7 tests: Remove self spawning integration tests
Fixes: #1925

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-11-09 00:16:15 +01:00
dependabot-preview[bot]
2ea0d8eb91 build(deps): bump cc from 1.0.61 to 1.0.62
Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.61 to 1.0.62.
- [Release notes](https://github.com/alexcrichton/cc-rs/releases)
- [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.61...1.0.62)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-06 22:50:38 +00:00
dependabot-preview[bot]
6a25aaf6b9 build(deps): bump url from 2.1.1 to 2.2.0
Bumps [url](https://github.com/servo/rust-url) from 2.1.1 to 2.2.0.
- [Release notes](https://github.com/servo/rust-url/releases)
- [Commits](https://github.com/servo/rust-url/compare/v2.1.1...v2.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-06 09:06:10 +00:00
dependabot-preview[bot]
1b6b45bf2f build(deps): bump thiserror from 1.0.21 to 1.0.22
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.21 to 1.0.22.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.21...1.0.22)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-04 16:24:46 +00:00
dependabot-preview[bot]
ecda97f759 build(deps): bump micro_http from 40309b7 to 59ab644
Bumps [micro_http](https://github.com/firecracker-microvm/micro-http) from `40309b7` to `59ab644`.
- [Release notes](https://github.com/firecracker-microvm/micro-http/releases)
- [Commits](40309b72ee...59ab64440a)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-04 16:01:50 +00:00
Michael Zhao
5566992422 scripts: Fix the failure to fetch latest guest kernel code on AArch64
The integration script failed to obtain the new guest kernel commit when
the code folder had been existing on CI machine.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-11-04 16:00:12 +00:00
dependabot-preview[bot]
cc637f12f6 build(deps): bump aho-corasick from 0.7.14 to 0.7.15
Bumps [aho-corasick](https://github.com/BurntSushi/aho-corasick) from 0.7.14 to 0.7.15.
- [Release notes](https://github.com/BurntSushi/aho-corasick/releases)
- [Commits](https://github.com/BurntSushi/aho-corasick/compare/0.7.14...0.7.15)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-04 15:15:55 +00:00
dependabot-preview[bot]
592babaadd build(deps): bump ppv-lite86 from 0.2.9 to 0.2.10
Bumps [ppv-lite86](https://github.com/cryptocorrosion/cryptocorrosion) from 0.2.9 to 0.2.10.
- [Release notes](https://github.com/cryptocorrosion/cryptocorrosion/releases)
- [Commits](https://github.com/cryptocorrosion/cryptocorrosion/compare/ppv-lite86-0.2.9...ppv-lite86-0.2.10)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-03 08:31:08 +00:00
dependabot-preview[bot]
138a8156c8 build(deps): bump blake2b_simd from 0.5.10 to 0.5.11
Bumps [blake2b_simd](https://github.com/oconnor663/blake2_simd) from 0.5.10 to 0.5.11.
- [Release notes](https://github.com/oconnor663/blake2_simd/releases)
- [Commits](https://github.com/oconnor663/blake2_simd/compare/0.5.10...0.5.11)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-03 08:30:59 +00:00
dependabot-preview[bot]
7a008e66a4 build(deps): bump anyhow from 1.0.33 to 1.0.34
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.33 to 1.0.34.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.33...1.0.34)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-03 08:30:50 +00:00
Michael Zhao
164d481683 tests: Enable watchdog test case on AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-11-02 08:19:07 +00:00
Michael Zhao
52f60188ca resources: Enable watchdog in guest driver
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-11-02 08:19:07 +00:00
dependabot-preview[bot]
8cb29af712 build(deps): bump regex from 1.4.1 to 1.4.2
Bumps [regex](https://github.com/rust-lang/regex) from 1.4.1 to 1.4.2.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.4.1...1.4.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-02 08:17:11 +00:00
dependabot-preview[bot]
60768a84c5 build(deps): bump signal-hook-registry from 1.2.1 to 1.2.2
Bumps [signal-hook-registry](https://github.com/vorner/signal-hook) from 1.2.1 to 1.2.2.
- [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/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-01 09:24:50 +00:00
dependabot-preview[bot]
3266eb7cce build(deps): bump backtrace from 0.3.53 to 0.3.54
Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.53 to 0.3.54.
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.53...0.3.54)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-31 07:42:56 +00:00
Muminul Islam
c9a28312a9 rpm: Fix vhost_user_block binary name and use latest tag
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-10-31 07:42:39 +00:00
Michael Zhao
a278704ae0 tests: Enable reboot test case on AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-10-30 17:14:44 +00:00
Michael Zhao
093a581ee1 vmm: Implement VM rebooting on AArch64
The logic to handle AArch64 system event was: SHUTDOWN and RESET were
all treated as RESET.

Now we handle them differently:
- RESET event will trigger Vmm::vm_reboot(),
- SHUTDOWN event will trigger Vmm::vm_shutdown().

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-10-30 17:14:44 +00:00
Michael Zhao
69394c9c35 vmm: Handle hypervisor VCPU run result from Vcpu to VcpuManager
Now Vcpu::run() returns a boolean value to VcpuManager, indicating
whether the VM is going to reboot (false) or just continue (true).
Moving the handling of hypervisor VCPU run result from Vcpu to
VcpuManager gives us the flexibility to handle more scenarios like
shutting down on AArch64.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-10-30 17:14:44 +00:00
Michael Zhao
0f5e5d9e6d tests: Fix some build warnings in integration test on AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-10-30 17:14:12 +00:00
Michael Zhao
4606f0f28a tests: Make migration test case X86 only
Set the test case test_snapshot_restore X86 only, instead of excluding
it from test command line.

The command line option was added because we used to support migration
with Virtio-MMIO, but not Virtio-PCI.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-10-30 17:14:12 +00:00
Rob Bradford
cb88ceeae8 vmm: memory_manager: Move the restoration of guest memory later
Rather than filling the guest memory from a file at the point of the the
guest memory region being created instead fill from the file later. This
simplifies the region creation code but also adds flexibility for
sourcing the guest memory from a source other than an on disk file.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-30 12:31:47 +01:00
Rob Bradford
7dcd3aff05 build, release-notes.md: Document 0.11.0 release
Update release notes and version number for the new release.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-29 17:36:02 +00:00
Bo Chen
8c268e351c tests: Port more tests to use wait_vm_boot
Tests not ported include 1) the ones that start guest VMs without
network (e.g. test_net_hotplug, test_initramfs), 2) test_vfio that
involves l2 guest. Also, some tests that use bionic guest image are
given extended timeout (120s) for 'wait_vm_boot'.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-10-29 15:30:17 +00:00
Bo Chen
a79f058a90 tests: Accept custom timeout for wait_vm_boot
This allows known slow tests to have a longer/customized timeout while
keeping the default timeout short.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-10-29 15:30:17 +00:00
Bo Chen
26783fea89 tests: Wait explicitly for vm shutdown w/ the 'wait-timeout' crate
Instead of waiting blindly with fixed amount of sleeping time, we can
use the `wait-timeout` crate to explicitly wait VM shutdown (with a
timeout). It can reduces the execution time of some tests
substantially. Also, this patch increases the `shutdown` timeout for
'test_reboot', which should fix the recent sporadic failures on this
test.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-10-29 15:30:17 +00:00
Bo Chen
cd1c2ed31e build: Add the 'v' prefix when using the crate version
Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-10-29 08:19:25 -07:00
dependabot-preview[bot]
b947320feb build(deps): bump memchr from 2.3.3 to 2.3.4
Bumps [memchr](https://github.com/BurntSushi/rust-memchr) from 2.3.3 to 2.3.4.
- [Release notes](https://github.com/BurntSushi/rust-memchr/releases)
- [Commits](https://github.com/BurntSushi/rust-memchr/compare/2.3.3...2.3.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-29 09:24:32 +00:00
Rob Bradford
d54544046c build: Use stable virtio-fs QEMU branch
Address build failure from activity in the development virtio-fs branch
by using the stable fork.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-29 08:52:25 +00:00
Bo Chen
8c92d1dbdc tests: Wait explicitly for the guest vm to boot
Instead of blindly waiting for 20-40s for the guest VM to boot, this
patch waits the notification from the guest VM explicitly by using a
simple TcpListener on the host and a custom systemd service in the
guest.

This patch also ported few tests to use this new machanism, while more
tests are to be ported.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-10-28 11:27:25 -07:00
dependabot-preview[bot]
cc67a05474 build(deps): bump proc-macro-hack from 0.5.18 to 0.5.19
Bumps [proc-macro-hack](https://github.com/dtolnay/proc-macro-hack) from 0.5.18 to 0.5.19.
- [Release notes](https://github.com/dtolnay/proc-macro-hack/releases)
- [Commits](https://github.com/dtolnay/proc-macro-hack/compare/0.5.18...0.5.19)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-28 08:04:11 +00:00
Rob Bradford
21db6f53c8 vmm: memory_manager: Write all guest region to disk
As a mirror of bdbea19e23 which ensured
that GuestMemoryMmap::read_exact_from() was used to read all the file to
the region ensure that all the guest memory region is written to disk.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-27 12:11:31 -07:00
Rob Bradford
be1b6bc1e1 main: Remove API socket when exiting
When exiting remove the API socket from the filesystem.

Fixes: #1241

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-27 13:27:23 +00:00
Rob Bradford
c22b788b47 main: Simplify error and return handling in start_vmm
Use a Result<> type with an error to simplify the code in start_vmm().
This will also make it easier to add cleanup funtionality.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-27 13:27:23 +00:00
Rob Bradford
dfd21cbfc5 vmm: Use thiserror/anyhow for vmm::Error
This gives a nicer user experience and this error can now be used as the
source for other errors based off this.

See: #1910

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-27 13:27:23 +00:00
Rob Bradford
6d4656c68f virtio-devices: seccomp_filters: Add fsync to block io_uring filter
This is required when booting with hypervisor-fw.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-27 10:53:54 +00:00
Rob Bradford
338521c700 build: Enable io_uring feature by default
Now that we that our CI is running with a kernel that is new enough to
support io_uring we can turn this feature on by default.

See: #1561

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-27 10:53:54 +00:00
Muminul Islam
2e1866a5db scripts: dev_cli: Add an option to dev_cli to export volumes
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-10-27 09:52:35 +00:00
Rob Bradford
8bd3fdea8f build: Move on-demand workers from bionic to groovy
This is an interim step to be able to test io_uring on our CI system.

See: #1561

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-26 14:27:20 -07:00
dependabot-preview[bot]
f0d0d8ccaf build(deps): bump libc from 0.2.79 to 0.2.80
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.79 to 0.2.80.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.79...0.2.80)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-26 09:31:03 +00:00
dependabot-preview[bot]
0415146018 build(deps): bump syn from 1.0.46 to 1.0.48
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.46 to 1.0.48.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.46...1.0.48)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-24 21:58:39 +00:00
dependabot-preview[bot]
499fbd0367 build(deps): bump futures from 0.3.6 to 0.3.7
Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.6 to 0.3.7.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.6...0.3.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-24 00:08:41 +00:00
dependabot-preview[bot]
e70674943f build(deps): bump futures-sink from 0.3.6 to 0.3.7
Bumps [futures-sink](https://github.com/rust-lang/futures-rs) from 0.3.6 to 0.3.7.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.6...0.3.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-23 20:00:07 +00:00
Sebastien Boeuf
7e127df415 vmm: memory_manager: Replace 'ext_region' by 'saved_region'
Any occurrence of of a variable containing `ext_region` is replaced with
the less confusing name `saved_region`. The point is to clearly identify
the memory regions that might have been saved during a snapshot, while
the `ext` standing for `external` was pretty unclear.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-23 21:59:52 +02:00
Sebastien Boeuf
c0e8e5b53f vmm: memory_manager: Replace 'backing_file' variable names
In the context of saving the memory regions content through snapshot,
using the term "backing file" brings confusion with the actual backing
file that might back the memory mapping.

To avoid such conflicting naming, the 'backing_file' field from the
MemoryRegion structure gets replaced with 'content', as this is
designating the potential file containing the memory region data.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-23 21:59:52 +02:00
dependabot-preview[bot]
1409b36cad build(deps): bump futures-task from 0.3.6 to 0.3.7
Bumps [futures-task](https://github.com/rust-lang/futures-rs) from 0.3.6 to 0.3.7.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.6...0.3.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-23 18:58:11 +00:00
dependabot-preview[bot]
cf067d94c3 build(deps): bump futures-io from 0.3.6 to 0.3.7
Bumps [futures-io](https://github.com/rust-lang/futures-rs) from 0.3.6 to 0.3.7.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.6...0.3.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-23 18:57:45 +00:00
dependabot-preview[bot]
c377c1398f build(deps): bump futures-macro from 0.3.6 to 0.3.7
Bumps [futures-macro](https://github.com/rust-lang/futures-rs) from 0.3.6 to 0.3.7.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.6...0.3.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-23 18:57:26 +00:00
dependabot-preview[bot]
b64a48adb8 build(deps): bump arrayvec from 0.5.1 to 0.5.2
Bumps [arrayvec](https://github.com/bluss/arrayvec) from 0.5.1 to 0.5.2.
- [Release notes](https://github.com/bluss/arrayvec/releases)
- [Changelog](https://github.com/bluss/arrayvec/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bluss/arrayvec/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-23 17:27:29 +00:00
Rob Bradford
bdbea19e23 vmm: memory_manager: Completely fill guest ram from snapshot
Use GuestRegionMmap::read_exact_from() to ensure that all of the file is
read into the guest. This addresses an issue where
GuestRegionMmap::read_from() was only copying the first 2GiB of the
memory and so lead to snapshot-restore was failing when the guest RAM
was 2GiB or greater.

This change also propagates any error from the copying upwards.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-23 17:56:19 +01:00
Rob Bradford
8de3bd728c ch-remote, api_client: Split HTTP/API client code into new crate
Split out the HTTP request handling code from ch-remote into a new
crate which can be used in other places where talking to the API server
by HTTP is necessary.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-23 14:50:36 +02:00
Rob Bradford
654846f433 bin: ch-remote: Generalise functions that work on a HTTP socket
Use the trait for Read/Write rather than specifying the concrete type.
This allows for the functionality to be used for different socket types.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-23 14:50:36 +02:00
Rob Bradford
a60b437f89 vmm: memory_manager: Always copy anonymous RAM regions from disk
When restoring if a region of RAM is backed by anonymous memory i.e from
memfd_create() then copy the contents of the ram from the file that has
been saved to disk.

Previously the code would map the memory from that file into the guest
using a MAP_PRIVATE mapping. This has the effect of
minimising the restore time but provides an issue where the restored VM
does not have the same structure as the snapshotted VM, in particular
memory is backed by files in the restored VM that were anonymously
backed in the original.

This creates two problems:

* The snapshot data is mapped from files for the pages of the guest
  which prevents the storage from being reclaimed.
* When snapshotting again the guest memory will not be correctly saved
  as it will have looked like it was backed by a file so it will not be
  written to disk but as it is a MAP_PRIVATE mapping the changes will
  never be written to the disk again. This results in incorrect
  behaviour.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-23 12:34:32 +02:00
Wei Liu
255dbd29ef tests: factor out windows_auth
This avoid repetition once we have more Windows tests.

No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-10-22 18:23:08 +02:00
Wei Liu
2902a96ae6 tests: add Windows guest snapshot test
We also need to restrict the number of test threads to 1 to avoid tests
interfere with each other.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-10-22 18:23:08 +02:00
Sebastien Boeuf
89b3d7b49b ci: Update integration tests with latest balloon changes
Now that virtio-balloon is not declared as part of the --memory
parameter, the integration tests are updated to keep the correct
behavior.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-22 16:33:16 +02:00
Sebastien Boeuf
f4e391922f vmm: Remove balloon options from --memory parameter
The standalone `--balloon` parameter being fully functional at this
point, we can get rid of the balloon options from the --memory
parameter.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-22 16:33:16 +02:00
Sebastien Boeuf
3594685279 vmm: Move balloon code from MemoryManager to DeviceManager
Now that we have a new dedicated way of asking for a balloon through the
CLI and the REST API, we can move all the balloon code to the device
manager. This allows us to simplify the memory manager, which is already
quite complex.

It also simplifies the behavior of the balloon resizing command. Instead
of providing the expected size for the RAM, which is complex when memory
zones are involved, it now expects the balloon size. This is a much more
straightforward behavior as it really resizes the balloon to the desired
size. Additionally to the simplication, the benefit of this approach is
that it does not need to be tied to the memory manager at all.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-22 16:33:16 +02:00
Sebastien Boeuf
1d479e5e08 vmm: Introduce new --balloon parameter
This introduces a new way of defining the virtio-balloon device. Instead
of going through the --memory parameter, the idea is to consider balloon
as a standalone virtio device.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-22 16:33:16 +02:00
dependabot-preview[bot]
ae296d2229 build(deps): bump syn from 1.0.45 to 1.0.46
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.45 to 1.0.46.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.45...1.0.46)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-22 06:53:06 +00:00
dependabot-preview[bot]
555610181b build(deps): bump rustc-demangle from 0.1.17 to 0.1.18
Bumps [rustc-demangle](https://github.com/alexcrichton/rustc-demangle) from 0.1.17 to 0.1.18.
- [Release notes](https://github.com/alexcrichton/rustc-demangle/releases)
- [Commits](https://github.com/alexcrichton/rustc-demangle/compare/0.1.17...0.1.18)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-21 21:26:57 +00:00
Sebastien Boeuf
28e12e9f3a vmm, hypervisor: Fix snapshot/restore for Windows guest
The snasphot/restore feature is not working because some CPU states are
not properly saved, which means they can't be restored later on.

First thing, we ensure the CPUID is stored so that it can be properly
restored later. The code is simplified and pushed down to the hypervisor
crate.

Second thing, we identify for each vCPU if the Hyper-V SynIC device is
emulated or not. In case it is, that means some specific MSRs will be
set by the guest. These MSRs must be saved in order to properly restore
the VM.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-21 19:11:03 +01:00
Rob Bradford
700f63fad8 tests: Add integration test for virtio-watchdog
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-21 16:02:39 +01:00
Rob Bradford
7ee63134d2 resources: Update Linux config to enable virtio-watchdog
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-21 16:02:39 +01:00
Rob Bradford
885ee9567b vmm: Add support for creating virtio-watchdog
The watchdog device is created through the "--watchdog" parameter. At
most a single watchdog can be created per VM.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-21 16:02:39 +01:00
Rob Bradford
d2c7645731 virtio-devices: Add simple virtio-watchdog device
This device operates a single virtq. When the driver offers a descriptor
to the device it is interpreted as a "ping" to indicate that the guest
is alive. A periodic timer fires and if when the timer is fired there
has not been a "ping" from the guest then the device will reset the VM.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-21 16:02:39 +01:00
Rob Bradford
ae375434cd vm-virtio: Add (temporary) number allocation for virtio-watchdog
The next available number for allocation is 35.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-21 16:02:39 +01:00
Michael Zhao
0b0596ef30 arch: Simplify PCI space address handling in AArch64 FDT
Before Virtio-mmio was removed, we passed an optional PCI space address
parameter to AArch64 code for generating FDT. The address is none if the
transport is MMIO.
Now Virtio-PCI is the only option, the parameter is mandatory.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-10-21 12:20:30 +01:00
Bo Chen
e83d99ab10 tests: Run binary with INFO (-v) level logging
Given the increased amount of output from cloud-hypervisor, this patch
also increased the PIPE_SIZE to 32MB (from 256KB).

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-10-21 08:48:28 +01:00
Bo Chen
e869d2f1bc tests: Print full commandline for better debugging
This patch prints the complete commandline when launching
cloud-hypervisor. It also prints the details of the `ssh` command if
the command is failing.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-10-21 08:48:28 +01:00
Muminul Islam
5867a1af4a hypervisor: Update Author and license info in the toml file
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-10-20 11:51:32 +01:00
Rob Bradford
e9880ab0d1 vhost_user_fs: seccomp: Propagate error correctly
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-19 21:53:38 -07:00
Rob Bradford
02621c6150 vhost_user_fs: sandbox: Fix clippy errors
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-19 21:53:38 -07:00
Rob Bradford
cf86ca15c2 virtio-devices: vsock: Fix clippy issue in tests
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-19 21:53:38 -07:00
Rob Bradford
05c79119b9 virtio-devices: pci_common_config: Fix clippy issues in tests
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-19 21:53:38 -07:00
Rob Bradford
c4dc25de09 hypervisor: kvm: aarch64: Trigger reset upon KVM_SYSTEM_EVENT_RESET
This will trigger Vm::vm_reboot to make the VM reboot.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-20 12:46:35 +08:00
Anatol Belski
b076602b87 doc: Add Windows debug instructions
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2020-10-19 16:31:26 +01:00
Michael Zhao
2f2e10ea35 arch: Remove GICv2
Virtio-mmio is removed, now virtio-pci is the only option for virtio
transport layer. We use MSI for PCI device interrupt. While GICv2, the
legacy interrupt controller, doesn't support MSI. So GICv2 is not very
practical for Cloud-hypervisor, we can remove it.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-10-19 14:58:48 +01:00
Sebastien Boeuf
58474854f2 docs: Remove all virtio-mmio references
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-19 14:58:48 +01:00
Sebastien Boeuf
8b9c9bc97f ci: Remove all references to 'mmio' feature
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-19 14:58:48 +01:00
Sebastien Boeuf
f73a345107 scripts: Remove all references to 'mmio' feature
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-19 14:58:48 +01:00
Sebastien Boeuf
74c08e5669 github-actions: Remove all references to 'mmio' feature
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-19 14:58:48 +01:00
Sebastien Boeuf
cc8b553e86 virtio-devices: Remove mmio and pci differentiation
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-19 14:58:48 +01:00
Sebastien Boeuf
af3c6c34c3 vmm: Remove mmio and pci differentiation
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-19 14:58:48 +01:00
pierwill
d2741fdc84 docs: Edit README.md
Add link to issue and fix two typos.

Signed-off-by: pierwill <19642016+pierwill@users.noreply.github.com>
2020-10-19 07:30:13 +02:00
dependabot-preview[bot]
9c6b03927a build(deps): bump syn from 1.0.44 to 1.0.45
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.44 to 1.0.45.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.44...1.0.45)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-19 05:28:55 +00:00
dependabot-preview[bot]
d986f74e27 build(deps): bump serde_derive from 1.0.116 to 1.0.117
Bumps [serde_derive](https://github.com/serde-rs/serde) from 1.0.116 to 1.0.117.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.116...v1.0.117)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-16 09:02:37 +00:00
dependabot-preview[bot]
fee873e325 build(deps): bump serde from 1.0.116 to 1.0.117
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.116 to 1.0.117.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.116...v1.0.117)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-16 08:21:05 +00:00
Sebastien Boeuf
7cbd47a71a vmm: Prevent KVM device fd from being unusable from VfioContainer
When shutting down a VM using VFIO, the following error has been
detected:

vfio-ioctls/src/vfio_device.rs:312 -- Could not delete VFIO group:
KvmSetDeviceAttr(Error(9))

After some investigation, it appears the KVM device file descriptor used
for removing a VFIO group was already closed. This is coming from the
Rust sequence of Drop, from the DeviceManager all the way down to
VfioDevice.

Because the DeviceManager owns passthrough_device, which is effectively
a KVM device file descriptor, when the DeviceManager is dropped, the
passthrough_device follows, with the effect of closing the KVM device
file descriptor. Problem is, VfioDevice has not been dropped yet and it
still needs a valid KVM device file descriptor.

That's why the simple way to fix this issue coming from Rust dropping
all resources is to make Linux accountable for it by duplicating the
file descriptor. This way, even when the passthrough_device is dropped,
the KVM file descriptor is closed, but a duplicated instance is still
valid and owned by the VfioContainer.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-15 19:15:28 +02:00
Wei Liu
d667ed0c70 vmm: don't call notify_guest_clock_paused when Hyper-V emulation is on
We turn on that emulation for Windows. Windows does not have KVM's PV
clock, so calling notify_guest_clock_paused results in an error.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-10-15 19:14:25 +02:00
Sebastien Boeuf
0c967e1aa0 virtio-devices: iommu: Update the list of seccomp filters
While using the virtio-iommu device involving L2 scenario, and tearing
things down all the way from L2 back to L0 exposed some bad syscalls
that were not part of the authorized list.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-14 19:15:09 +02:00
Wei Liu
57f81d0375 scripts: dev_cli: clarify which integration test is running
This makes it easier to grep. No functional change obviously.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-10-14 14:23:11 +02:00
Rob Bradford
1bae38ceb4 build: Add Jenkinsfile entry for Windows guest
Add one more parallel stage to run Windows guest tests in a dedicated
VM.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-14 11:19:29 +02:00
Rob Bradford
934f992536 scripts: dev_cli: Add support for Windows guest integration tests
Now that we've written Windows integration tests and the associated
script to launch them, this patch enables the support for Windows tests
in dev_cli.sh, so that we can run it in our Cloud Hypervisor container.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-14 11:19:29 +02:00
Rob Bradford
76c04878fa scripts: Add wrapper script to run Windows guest integration tests
Adding a dedicated script to avoid confusion with other Linux
integration tests scripts.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-14 11:19:29 +02:00
Rob Bradford
d598341534 tests: Add Windows guest integration test
This is a new integration test running Windows as a guest with Cloud
Hypervisor. Once the VM is booted, the test connects to the guest
through SSH and shutdown the VM. If this succeeds, this means the VM
was properly booted to userspace and that the network was functional.

Important to note that because this test generates lots of logs, it
requires a large pipe size for both stdout and stderr.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-14 11:19:29 +02:00
Rob Bradford
0eabc00b27 tests: Allow controlling the password for SSH auth
The login details for the Windows VM are different.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-14 11:19:29 +02:00
dependabot-preview[bot]
08ded4b449 build(deps): bump regex from 1.4.0 to 1.4.1
Bumps [regex](https://github.com/rust-lang/regex) from 1.4.0 to 1.4.1.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.4.0...1.4.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-13 17:41:10 +00:00
Sebastien Boeuf
9d882bc8fe ci: Add integration test for testing maximum physical bits
Introduce a new test that will validate the new option `max_phys_bits`
from the `--cpus` parameter behaves as expected.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-13 18:58:36 +02:00
Sebastien Boeuf
1b9890b807 vmm: cpu: Set CPU physical bits based on user input
If the user specified a maximum physical bits value through the
`max_phys_bits` option from `--cpus` parameter, the guest CPUID
will be patched accordingly to ensure the guest will find the
right amount of physical bits.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-13 18:58:36 +02:00
Sebastien Boeuf
aec88e20d7 vmm: memory_manager: Rely on physical bits for address space size
If the user provided a maximum physical bits value for the vCPUs, the
memory manager will adapt the guest physical address space accordingly
so that devices are not placed further than the specified value.

It's important to note that if the number exceed what is available on
the host, the smaller number will be picked.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-13 18:58:36 +02:00
Sebastien Boeuf
52ad78886c vmm: Introduce new CPU option to set maximum physical bits
In order to let the user choose maximum address space size, this patch
introduces a new option `max_phys_bits` to the `--cpus` parameter.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-13 18:58:36 +02:00
dependabot-preview[bot]
c97824ab76 build(deps): bump pkg-config from 0.3.18 to 0.3.19
Bumps [pkg-config](https://github.com/rust-lang/pkg-config-rs) from 0.3.18 to 0.3.19.
- [Release notes](https://github.com/rust-lang/pkg-config-rs/releases)
- [Changelog](https://github.com/rust-lang/pkg-config-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/pkg-config-rs/compare/0.3.18...0.3.19)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-13 13:14:47 +00:00
Bo Chen
e9738a4a49 vmm: Replace the use of 'unchecked_add' with 'checked_add'
The 'GuestAddress::unchecked_add' function has undefined behavior when
an overflow occurs. Its alternative 'checked_add' requires use to handle
the overflow explicitly.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-10-13 12:09:22 +02:00
Bo Chen
9ab2a34b40 vmm: Remove reserved 256M gaps for hotplugging memory with ACPI
We are now reserving a 256M gap in the guest address space each time
when hotplugging memory with ACPI, which prevents users from hotplugging
memory to the maximum size they requested. We confirm that there is no
need to reserve this gap.

This patch removes the 'reserved gaps'. It also refactors the
'MemoryManager::start_addr' so that it is rounding-up to 128M alignment
when hotplugged memory is allowed with ACPI.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-10-13 12:09:22 +02:00
Henry Wang
8bf0bac5a7 dev_cli: Fix TARGETARCH inconsistancy
In previous dev_cli.sh, the `uname -m` command will generate
either `x86_64` or `aarch64`, which is inconsistent with the
architectures in the Dockerfile, namely `amd64` and `arm64`.

This will cause some dependancy missing in the docker container
when the docker image is built locally.

This commit fixes this inconsistancy.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-10-13 11:57:01 +02:00
dependabot-preview[bot]
ef1e5fd953 build(deps): bump serde_json from 1.0.58 to 1.0.59
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.58 to 1.0.59.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.58...v1.0.59)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-13 06:57:48 +00:00
dependabot-preview[bot]
a06a6e4696 build(deps): bump aho-corasick from 0.7.13 to 0.7.14
Bumps [aho-corasick](https://github.com/BurntSushi/aho-corasick) from 0.7.13 to 0.7.14.
- [Release notes](https://github.com/BurntSushi/aho-corasick/releases)
- [Commits](https://github.com/BurntSushi/aho-corasick/compare/0.7.13...0.7.14)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-13 06:57:37 +00:00
Bo Chen
10f380f95b vmm: Report no error when resizing to current memory size with ACPI
We now try to create a ram region of size 0 when the requested memory
size is the same as current memory size. It results in an error of
`GuestMemoryRegion(Mmap(Os { code: 22, kind: InvalidInput, message:
"Invalid argument" }))`. This error is not meaningful to users and we
should not report it.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-10-12 08:46:38 +02:00
dependabot-preview[bot]
299e83bf43 build(deps): bump regex from 1.3.9 to 1.4.0
Bumps [regex](https://github.com/rust-lang/regex) from 1.3.9 to 1.4.0.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.3.9...1.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-12 05:17:07 +00:00
dependabot-preview[bot]
54d2298a93 build(deps): bump regex-syntax from 0.6.18 to 0.6.19
Bumps [regex-syntax](https://github.com/rust-lang/regex) from 0.6.18 to 0.6.19.
- [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)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-12 05:16:46 +00:00
dependabot-preview[bot]
74627d2de5 build(deps): bump backtrace from 0.3.52 to 0.3.53
Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.52 to 0.3.53.
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.52...0.3.53)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-12 05:16:17 +00:00
dependabot-preview[bot]
818dc72e5f build(deps): bump pin-project from 0.4.26 to 0.4.27
Bumps [pin-project](https://github.com/taiki-e/pin-project) from 0.4.26 to 0.4.27.
- [Release notes](https://github.com/taiki-e/pin-project/releases)
- [Changelog](https://github.com/taiki-e/pin-project/blob/master/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project/compare/v0.4.26...v0.4.27)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-12 05:12:45 +00:00
dependabot-preview[bot]
a4be05ac40 build(deps): bump syn from 1.0.43 to 1.0.44
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.43 to 1.0.44.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.43...1.0.44)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-12 05:12:12 +00:00
Muminul Islam
029a6d8ab9 README: Add steps to install prerequisites
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-10-10 09:52:06 +02:00
Muminul Islam
0f48b61265 README: Syntax cleanups
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-10-10 09:52:06 +02:00
Bo Chen
789ee7b3e4 vmm: Support resizing memory up to and including hotplug size
The start address after the hottplugged memory can be the start address of
device area.

Fixes: #1803

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-10-10 09:51:32 +02:00
dependabot-preview[bot]
f639a8a0fd build(deps): bump syn from 1.0.42 to 1.0.43
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.42 to 1.0.43.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.42...1.0.43)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-09 17:56:30 +00:00
dependabot-preview[bot]
eabfd642e0 build(deps): bump cc from 1.0.60 to 1.0.61
Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.60 to 1.0.61.
- [Release notes](https://github.com/alexcrichton/cc-rs/releases)
- [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.60...1.0.61)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-09 10:23:32 +00:00
dependabot-preview[bot]
ab32375666 build(deps): bump backtrace from 0.3.51 to 0.3.52
Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.51 to 0.3.52.
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.51...0.3.52)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-09 09:33:32 +00:00
Michael Zhao
2a7b1d78ff build: Fix AArch64 musl cross build failure
A failure appeared in AArch64 musl cross build, after upgrading rust
to v1.47.0. A symbol "strrchr" was missing while linking against
static libfdt.a.

The issue could be caused by missing symbol(s) in new rust toolchain.

This fix pins the rust version in this cross build action to a stable-
enough version. Further upgrade will be done manually after testing.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-10-09 10:49:54 +02:00
Rob Bradford
573a5c63cf hypervisor: kvm: Use unstable_sort() to keep clippy happy
"Using a stable sort consumes more memory and cpu cycles. Because values
which compare equal are identical, preserving their relative order (the
guarantee that a stable sort provides) means nothing, while the extra
costs still apply."

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-09 10:49:54 +02:00
Rob Bradford
bb5b9584d2 pci, ch-remote, vmm: Replace simple match blocks with matches!
This is a new clippy check introduced in 1.47 which requires the use of
the matches!() macro for simple match blocks that return a boolean.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-09 10:49:54 +02:00
Sebastien Boeuf
2fac41f154 deps: Patch kvm-ioctls and kvm-bindings crates
Instead of having the hypervisor crate embedding Cloud-Hypervisor forks
from the rust-vmm project, it's more appropriate to leave the rust-vmm
references in the hypervisor crate, and have the root Cargo.toml being
patched.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-08 18:45:42 +02:00
Anatol Belski
095ea049e2 doc: Add UEFI and Windows consumer pages
This changeset extends the documentation with the UEFI and Windows
related info. The focus is on providing consumer with a minimum
necessary and proper piece of the information to enter the features
quickly. While UEFI is a cross platform topic, it is a required
prerequisite for the Windows usage.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2020-10-08 15:45:30 +01:00
dependabot-preview[bot]
ff0d2431d0 build(deps): bump rustc-demangle from 0.1.16 to 0.1.17
Bumps [rustc-demangle](https://github.com/alexcrichton/rustc-demangle) from 0.1.16 to 0.1.17.
- [Release notes](https://github.com/alexcrichton/rustc-demangle/releases)
- [Commits](https://github.com/alexcrichton/rustc-demangle/compare/0.1.16...0.1.17)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-08 08:59:34 +00:00
Wei Liu
ed1fdd1f7d hypervisor, arch: rename "OneRegister" and relevant code
The OneRegister literally means "one (arbitrary) register". Just call it
"Register" instead. There is no need to inherit KVM's naming scheme in
the hypervisor agnostic code.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-10-08 08:55:10 +02:00
Wei Liu
9ad14e6b3a aarch64: Add OneReg to the list required extensions for KVM
Without that capability save / restore for aarch64 won't work.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-10-08 08:54:38 +02:00
Sebastien Boeuf
30e1162d7c virtio: Replace some repr(C, packed) with repr(C)
The goal here is to replace anywhere possible a virtio structure
with a "C, packed" representation by a "C" representation. Some
virtio structures are not expected to be packed, therefore there's
no reason for using the more restrictive "C, packed" representation.

This is important since "packed" representation can still cause
undefined behaviors with Rust 2018.

By removing the need for "packed" representation, we can simplify a
bit of code by deriving the Serialize trait without writing the
implementation ourselves.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-07 22:11:36 +02:00
dependabot-preview[bot]
2333c5e233 build(deps): bump miniz_oxide from 0.4.2 to 0.4.3
Bumps [miniz_oxide](https://github.com/Frommi/miniz_oxide) from 0.4.2 to 0.4.3.
- [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.4.2...0.4.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-07 15:55:10 +00:00
Sebastien Boeuf
1e3a6cb450 vmm: Simplify some of the io_uring code
Small patch creating a dedicated `block_io_uring_is_supported()`
function for the non-io_uring case, so that we can simplify the
code in the DeviceManager.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-07 14:26:49 +02:00
Wei Liu
ac32b1e35f ci: use cargo check to validate building commits
The purpose of that step is to make sure each commit builds. The `check`
command is much faster for that purpose.

On my 32-core machine `cargo check --all` takes around 25 seconds while
`cargo build --all` takes around 35 seconds, so that's quite a bit of
time saving there.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-10-07 14:26:32 +02:00
Sebastien Boeuf
67025948dc ci: Simplify test scripts
Since all unit and integration tests are run inside containers because
they are called from dev_cli.sh, they always run as root. That's why
both unit and integration scripts can be simplified as they don't need
to apply specific capabilities and run cargo tests in a dedicated 'kvm'
group.

Fixes #1683

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-07 14:26:13 +02:00
dependabot-preview[bot]
a5d3604272 build(deps): bump anyhow from 1.0.32 to 1.0.33
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.32 to 1.0.33.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.32...1.0.33)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-07 06:58:14 +00:00
dependabot-preview[bot]
f48398083c build(deps): bump thiserror from 1.0.20 to 1.0.21
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.20 to 1.0.21.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.20...1.0.21)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-07 05:38:10 +00:00
Rob Bradford
00c0b9e170 devices: ioapic: Tolerate Windows writing zero to version register
Windows will write zero to the IOAPIC version register as part of
probing if the device is there.

Fixes: #1791

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-06 18:13:33 +01:00
Sebastien Boeuf
162789a2d1 ci: Extend virtio-blk hotplug integration test
The existing virtio-blk hotplug test is extended by removing and
re-adding the virtio-blk device. This ensures the unplug/re-plug
feature is properly tested.

Fixes #1809

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-06 17:22:29 +01:00
Sebastien Boeuf
14163c5200 ci: Extend virtio-net hotplug integration test
The existing virtio-net hotplug test is extended by removing and
re-adding the virtio-net device. This ensures the unplug/re-plug
feature is properly tested.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-06 17:22:29 +01:00
Rob Bradford
8824da27cb docs: Add documentation about the log levels and when to use them
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-06 16:52:29 +01:00
Rob Bradford
03f7d39ce5 main: Set default log level to warn!() equivalent.
Using our standard configuration and default kernel we trigger no
messages at this level.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-06 16:52:29 +01:00
Sebastien Boeuf
c02a02edfc vmm: Allow unlink syscall for vCPU threads
Without the unlink(2) syscall being allowed, Cloud-Hypervisor crashes
when we remove a virtio-vsock device that has been previously added.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-06 16:05:59 +01:00
Sebastien Boeuf
cc7a5aca6c ci: Validate each commit can be built
It's important to ensure Cloud-Hypervisor's Git tree is bisectable, and
that's why this commit extends the existing build.yaml Github action.
This will validate that each commit from an incoming pull request can be
built.

Fixes #1808

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-06 14:28:54 +01:00
Sebastien Boeuf
b33969896b virtio-devices: Rely on vhost crate from Cloud-Hypervisor fork
The Cloud-Hypervisor fork of the vhost crate contains one small
additional patch compared to the rust-vmm upstream version, meant for
increasing the connection timeout.

This patch is intended to be merged in order to check if it helps our CI
fixing the vhost-user-blk flakes that we've been observing recently.

If it fixes it, we'll submit a similar patch upstream and switch back to
the upstream vhost crate, otherwise we'll simply switch back to the
upstream crate, discarding this patch.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-06 12:56:33 +02:00
Sebastien Boeuf
6aa5e21212 vmm: device_manager: Fix PCI device unplug issues
Because of the PCI refactoring that happened in the previous commit
d793cc4da3, the ability to fully remove a
PCI device was altered.

The refactoring was correct, but the usage of a generic function to pass
the same reference for both BusDevice, PciDevice and Any + Send + Sync
causes the Arc::ptr_eq() function to behave differently than expected,
as it does not match the references later in the code. That means we
were not able to remove the device reference from the MMIO and/or PIO
buses, which was leading to some bus range overlapping error once we
were trying to add a device again to the previous range that should have
been removed.

Fixes #1802

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-06 12:56:17 +02:00
dependabot-preview[bot]
a32bd2fae1 build(deps): bump hermit-abi from 0.1.16 to 0.1.17
Bumps [hermit-abi](https://github.com/hermitcore/libhermit-rs) from 0.1.16 to 0.1.17.
- [Release notes](https://github.com/hermitcore/libhermit-rs/releases)
- [Commits](https://github.com/hermitcore/libhermit-rs/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-06 09:25:31 +00:00
dependabot-preview[bot]
e553c053af build(deps): bump futures from 0.3.5 to 0.3.6
Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.5 to 0.3.6.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-06 06:34:18 +00:00
dependabot-preview[bot]
83f6aa47c9 build(deps): bump futures-core from 0.3.5 to 0.3.6
Bumps [futures-core](https://github.com/rust-lang/futures-rs) from 0.3.5 to 0.3.6.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-05 20:58:50 +00:00
dependabot-preview[bot]
a4ebb6399a build(deps): bump futures-task from 0.3.5 to 0.3.6
Bumps [futures-task](https://github.com/rust-lang/futures-rs) from 0.3.5 to 0.3.6.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-05 20:58:24 +00:00
dependabot-preview[bot]
0c25b4d9fb build(deps): bump futures-io from 0.3.5 to 0.3.6
Bumps [futures-io](https://github.com/rust-lang/futures-rs) from 0.3.5 to 0.3.6.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-05 20:57:51 +00:00
dependabot-preview[bot]
c2cc26fc82 build(deps): bump libc from 0.2.78 to 0.2.79
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.78 to 0.2.79.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.78...0.2.79)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-05 07:02:05 +00:00
dependabot-preview[bot]
03eebcede2 build(deps): bump pin-project from 0.4.25 to 0.4.26
Bumps [pin-project](https://github.com/taiki-e/pin-project) from 0.4.25 to 0.4.26.
- [Release notes](https://github.com/taiki-e/pin-project/releases)
- [Changelog](https://github.com/taiki-e/pin-project/blob/v0.4.26/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project/compare/v0.4.25...v0.4.26)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-04 21:22:01 +00:00
Praveen Paladugu
71c435ce91 hypervisor, vmm: Introduce VmmOps trait
Run loop in hypervisor needs a callback mechanism to access resources
like guest memory, mmio, pio etc.

VmmOps trait is introduced here, which is implemented by vmm module.
While handling vcpuexits in run loop, this trait allows hypervisor
module access to the above mentioned resources via callbacks.

Signed-off-by: Praveen Paladugu <prapal@microsoft.com>
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-02 16:42:55 +01:00
Rob Bradford
6a9934d933 build: Fix vm-memory bump build error
A new version of vm-memory was released upstream which resulted in some
components pulling in that new version. Update the version number used
to point to the latest version but continue to use our patched version
due to the fix for #1258

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-02 16:38:02 +01:00
Rob Bradford
2d457ab974 vmm: device_manager: Make PMEM "discard_writes" mode true CoW
The PMEM support has an option called "discard_writes" which when true
will prevent changes to the device from hitting the backing file. This
is trying to be the equivalent of "readonly" support of the block
device.

Previously the memory of the device was marked as KVM_READONLY. This
resulted in a trap when the guest attempted to write to it resulting a
VM exit (and recently a warning). This has a very detrimental effect on
the performance so instead make "discard_writes" truly CoW by mapping
the memory as `PROT_READ | PROT_WRITE` and using `MAP_PRIVATE` to
establish the CoW mapping.

Fixes: #1795

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-02 14:26:15 +02:00
Daniel Verkamp
6eeab85db0 qcow: avoid out-of-bounds access in alloc_refblocks
When all refblocks are consumed, the loop looking for the first free
cluster would access the element at refcounts[refcounts.len()], which is
out of bounds.  Modify the free cluster search loop to check that the
index is in bounds before accessing it.

Tested-by: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>

(cherry picked from crosvm commit f21572c7187c8beb9c6bfea6446351ae93200d01)

Fixes: #1792

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-10-02 09:43:09 +02:00
Hui Zhu
c75f8b2f89 virtio-balloon: Add memory_actual_size to vm.info to show memory actual size
The virtio-balloon change the memory size is asynchronous.
VirtioBalloonConfig.actual of balloon device show current balloon size.

This commit add memory_actual_size to vm.info to show memory actual size.

Signed-off-by: Hui Zhu <teawater@antfin.com>
2020-10-01 17:46:30 +02:00
Sebastien Boeuf
9dffc5da5c devices: ioapic: Always retrieve destination field on 8 bits
When the destination mode is physical, the destination field should
only be defined through bits 56-59, as defined in the IOAPIC spec. But
from the APIC specification, the APIC ID is always defined on 8 bits no
matter which destination mode is selected. That's why we always retrieve
the destination field based on bits 56-63.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-01 14:35:38 +01:00
dependabot-preview[bot]
a8c2d70869 build(deps): bump pin-project from 0.4.24 to 0.4.25
Bumps [pin-project](https://github.com/taiki-e/pin-project) from 0.4.24 to 0.4.25.
- [Release notes](https://github.com/taiki-e/pin-project/releases)
- [Changelog](https://github.com/taiki-e/pin-project/blob/master/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project/compare/v0.4.24...v0.4.25)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-01 11:15:43 +00:00
Bo Chen
a070f44a51 build: github: Add a new action to build cargo fuzz
Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-10-01 11:16:35 +01:00
Bo Chen
dda1df0a58 fuzz: Fix the building errors with recent changes
This patch adds two required dependencies to fuzz/Cargo.toml, and fixes
the building error on the 'block' fuzzer.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-10-01 11:16:35 +01:00
Rob Bradford
2c2e7016c7 main: Improve documentation for --kernel
Fixes: #1712

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-10-01 10:08:25 +01:00
Sebastien Boeuf
532b3063be ci: No need to build Docker image locally for arm64
Now that Docker images are automatically generated for both amd64 and
arm64 architectures, there's no need to generate the arm64 image locally
on the ARM CI during a CI run. The image should be available from
DockerHub instead.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-10-01 10:04:32 +01:00
dependabot-preview[bot]
91314e7b6c build(deps): bump serde_json from 1.0.57 to 1.0.58
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.57 to 1.0.58.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.57...v1.0.58)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-01 08:07:53 +00:00
dependabot-preview[bot]
8851b48ce6 build(deps): bump proc-macro2 from 1.0.23 to 1.0.24
Bumps [proc-macro2](https://github.com/alexcrichton/proc-macro2) from 1.0.23 to 1.0.24.
- [Release notes](https://github.com/alexcrichton/proc-macro2/releases)
- [Commits](https://github.com/alexcrichton/proc-macro2/compare/1.0.23...1.0.24)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-01 05:40:28 +00:00
dependabot-preview[bot]
76c3230e08 build(deps): bump libc from 0.2.77 to 0.2.78
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.77 to 0.2.78.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.77...0.2.78)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-01 05:40:02 +00:00
Rob Bradford
664c3ceda6 vmm: device_manager: Warn that vhost-user self spawning is deprecated
See #1724 for details.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-30 18:32:50 +02:00
Rob Bradford
0a4be7ddf5 vmm: "Cleanly" shutdown on SIGTERM
Write to the exit_evt EventFD which will trigger all the devices and
vCPUs to exit. This is slightly cleaner than just exiting the process as
any temporary files will be removed.

Fixes: #1242

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-30 18:32:16 +02:00
Sebastien Boeuf
8a11ef5ba6 ci: Move back to latest virtiofsd version
This commit moves back to the branch "virtio-fs-dev" from virtiofsd, as
we figured the changes needed to use this branch and the requirements
from the new meson build from QEMU.

It updates the container version to ensure the dev_cli.sh script will
rely on the latest container which contains the needed packages.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-30 13:10:23 +01:00
Sebastien Boeuf
1e5d35d13a resources: Finalize automated generation of the Docker image
By fixing the Dockerfile, we have now finalized the automated generation
of the Docker images for both architectures (amd64 and arm64).

Fixes #953

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-30 10:03:06 +01:00
Rob Bradford
df26b428b1 arch: x86_64: Copy CPU identification string into guest cpuid
This is stored in leaves 0x80000002 to 0x80000004 inclusive.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-30 08:18:08 +01:00
Bo Chen
6d30fe05e4 vmm: openapi: Add the 'iommu' and 'id' option to 'VmAddDevice'
This patch adds the missing the `iommu` and `id` option for
`VmAddDevice` in the openApi yaml to respect the internal data structure
in the code base. Also, setting the `id` explicitly for VFIO device
hotplug is required for VFIO device unplug through openAPI calls.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-30 08:17:44 +01:00
dependabot-preview[bot]
af0c4c1659 build(deps): bump backtrace from 0.3.50 to 0.3.51
Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.50 to 0.3.51.
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.50...0.3.51)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-29 20:25:50 +00:00
Julio Montes
668c563dac vmm: openapi: fix integers format
According to openAPI specification [1], the format for `integer` types
can be only `int32` or `int64`, unsigned and 8-bits integers are not
supported.
This patch replaces `uint64` with `int64`, `uint32` with `int32` and
`uint8` with `int32`.

[1]: https://swagger.io/specification/#data-types

Signed-off-by: Julio Montes <julio.montes@intel.com>
2020-09-29 12:55:40 -07:00
Rob Bradford
5a0d3277c8 vmm: vm: Replace \n newline character with \r
This allows the CMD prompt under SAC to be used without affecting getty
on Linux.

Fixes: #1770

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-29 16:10:12 +02:00
Wei Liu
4ef97d8ddb vmm: interrupts: clearly separate MsiInterruptGroup and InterruptRoute
MsiInterruptGroup doesn't need to know the internal field names of
InterruptRoute. Introduce two helper functions to eliminate references
to irq_fd. This is done similarly to the enable and disable helper
functions.

Also drop the pub keyword from InterruptRoute fields. It is not needed
anymore.

No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-09-29 13:51:35 +02:00
Sebastien Boeuf
db5d42ad41 resources: Fix Dockerfile to support multi-architecture
In order to support both amd64 and arm64, we rely on the TARGETARCH
variable that is passed from the docker buildx command, based on the
platform used to build the container image.

There is no way to rely directly on $(uname -m) to assign a variable
with the correct x86_64 or aarch64 values we're looking for. Both ENV
and ARG don't evaluate the command, which means they see it as a simple
string. Using RUN is the only way to evaluate a command.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-29 09:29:36 +02:00
dependabot-preview[bot]
315cd5a054 build(deps): bump pin-project from 0.4.23 to 0.4.24
Bumps [pin-project](https://github.com/taiki-e/pin-project) from 0.4.23 to 0.4.24.
- [Release notes](https://github.com/taiki-e/pin-project/releases)
- [Changelog](https://github.com/taiki-e/pin-project/blob/master/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project/compare/v0.4.23...v0.4.24)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-28 14:34:47 +00:00
Sebastien Boeuf
77e9fcdebd resources: Update Dockerfile to install missing Python packages
In order to build virtiofsd from the latest build system, the Python
package python3-setuptools is required.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-28 09:28:37 +02:00
Sebastien Boeuf
3534b6932a github: Add a new action to update the Docker image
The idea is to rely on this new Github Action to detect when the
Dockerfile is updated after a push to the master branch on the
repository.

Once triggered, this action builds the Docker image for both
linux/amd64 and linux/arm64 platforms, and updates it directly
on Docker Hub.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-28 08:25:11 +02:00
dependabot-preview[bot]
34dd3b83af build(deps): bump syn from 1.0.41 to 1.0.42
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.41 to 1.0.42.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.41...1.0.42)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-28 05:20:09 +00:00
dependabot-preview[bot]
e105611eb6 build(deps): bump proc-macro2 from 1.0.21 to 1.0.23
Bumps [proc-macro2](https://github.com/alexcrichton/proc-macro2) from 1.0.21 to 1.0.23.
- [Release notes](https://github.com/alexcrichton/proc-macro2/releases)
- [Commits](https://github.com/alexcrichton/proc-macro2/compare/1.0.21...1.0.23)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-28 05:19:46 +00:00
Praveen Paladugu
f10872e706 vmm: fix clippy warnings
Signed-off-by: Praveen Paladugu <prapal@microsoft.com>
2020-09-26 14:07:12 +01:00
Praveen Paladugu
4b32252028 hypervisor, vmm: fix clippy warnings
Signed-off-by: Praveen Paladugu <prapal@microsoft.com>
2020-09-26 14:07:12 +01:00
Praveen Paladugu
6ebeaa9246 option_parser: fix clippy warnings
Signed-off-by: Praveen Paladugu <prapal@microsoft.com>
2020-09-26 14:07:12 +01:00
Julio Montes
c54452c08a vmm: openapi: fix integers format
According to openAPI specification[1], the format for `integer` types
can be only `int32` or `int64`, unsigned integers are not supported.
This patch replaces `uint64` with `int64`.

[1]: https://swagger.io/specification/#data-types

Signed-off-by: Julio Montes <julio.montes@intel.com>
2020-09-26 14:05:51 +01:00
Rob Bradford
f762bc7573 arch: x86_64: Create MP table after SMBIOS table if space
In order to speed up the Linux boot (so as to avoid it having to scan a
large number of pages) place the MP table directly after the SMBIOS
table if there is sufficient room. The start address of the SMBIOS table
is one of the three (and the largest) location that the MP table can
also be located at.

Before:
[    0.000399] x86/PAT: Configuration [0-7]: WB  WC  UC- UC  WB  WP  UC- WT
[    0.014945] check: Scanning 1 areas for low memory corruption

After:
[    0.000284] x86/PAT: Configuration [0-7]: WB  WC  UC- UC  WB  WP  UC- WT
[    0.000421] found SMP MP-table at [mem 0x000f0090-0x000f009f]

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-25 19:41:24 +02:00
Wei Liu
7e130a65ba vmm: interrupts: adjust set_gsi_routes
There is no point in manually dropping the lock for gsi_msi_routes then
instantly grabbing it again in set_gsi_routes.

Make set_gsi_routes take a reference to the routing hashmap instead.

No functional change intended.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-09-25 17:17:35 +02:00
Hui Zhu
4913acc05e vmm: Add 'balloon' to memory parameters
Add the option 'balloon' to --memory.

Signed-off-by: Hui Zhu <teawater@antfin.com>
2020-09-25 17:13:39 +02:00
Sebastien Boeuf
c85e396ce5 vmm: cpu: x86: Enable MTRR feature in CPUID
The MTRR feature was missing from the CPUID, which is causing the guest
to ignore the MTRR settings exposed through dedicated MSRs.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-25 15:03:52 +02:00
Rob Bradford
f4ec915c5d resources: Remove unused PPS features from kernel config
In particular this removes the annoying PPS messages that fill up the
dmesg log.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-25 14:07:41 +02:00
Sebastien Boeuf
ae44e9c076 resources: Reduce x86_64 kernel configuration to fix warnings
Removing the ISA DMA configurations prevents the kernel from accessing
the port I/O 0x87, which was generating the following warning:

WARN:vmm/src/cpu.rs:378 -- Guest PIO read to unregistered address 0x87

Removing the TELCLOCK configuration prevents the kernel from accessing
the port I/O reserved for the memory manager, which was causing the
following warning:

WARN:vmm/src/memory_manager.rs:289 -- Unexpected offset for accessing
memory manager device: 15

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-25 10:22:28 +01:00
Rob Bradford
29b74804e1 main: Improve the error reporting when creating the hypervisor object
The ::new() does very little beyond trying to open the /dev/kvm device
so provide a hint to the user about what has gone wrong.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-25 11:08:01 +02:00
Bo Chen
1d3c3bc6ec tests: Capture child process stdout/err in 'test_memory_mergeable'
Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-25 08:40:23 +02:00
Bo Chen
2441798fe4 tests: Resize the pipe size to 256K for capturing child stdout/err
As discussed in #1707, the `vcpu` thread can be stalled when using
`--serial tty`. To workaround that issue, this patch enforces to resize
the pipe size to 256K when we capture the stdout/stderr of the
cloud-hypervisor child process in the integration tests. Note that the
pipe size (256K) is chosen based on the output size of our integration
tests at this point, which may need to be increased in the future.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-25 08:40:23 +02:00
Bo Chen
365b947023 tests: Port test_simple_launch to the new methodology
This is the last test to be ported to the new methodology.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-25 08:40:23 +02:00
Bo Chen
cb2f11724a tests: Port test_reboot to the new methodology
Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-25 08:40:23 +02:00
Hui Zhu
d03a48162f balloon.rs: BalloonEpollHandler: Fix wrong error in handle_event
error!("Unknown event for virtio-mem");
This error should be
error!("Unknown event for virtio-balloon");

Signed-off-by: Hui Zhu <teawater@antfin.com>
2020-09-25 08:36:23 +02:00
Sebastien Boeuf
de88bef429 pci: msix: Fix masking/enabling semantics
By looking at Linux kernel boot time, we identified that a lot of time
was spent registering and unregistering IRQ fds to KVM. This is not
efficient and certainly not a wrong behavior from the Linux kernel,
but rather a problem with the Cloud-Hypervisor's implementation of
MSI-X.

The way to fix this issue is by ensuring the initial conditions are
correct, which means the entire MSI-X vector table must be disabled
and masked. Additionally, each vector must be individually masked.

With these correct conditions, Linux won't start masking interrupt
vectors, and later unmask them since they will be seen as masked from
the beginning. This means the OS will simply have to unmask them when
needed, avoiding the extra operation.

Another aspect of this patch is to prevent Cloud-Hypervisor from
enabling (by registering IRQ fd) all vectors when either the global
'mask' or 'enable' bits are set. Instead, we can simply let the mask()
and unmask() operations take care of it if needed.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-24 22:29:16 +02:00
Sebastien Boeuf
64351c1f3f build: Update Cargo.lock
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-23 19:03:19 +02:00
Sebastien Boeuf
2eaf1c70c0 vmm: acpi: Advertise the correct PCI bus range
Since Cloud-Hypervisor currently support one single PCI bus, we must
reflect this through the MCFG table, as it advertises the first bus and
the last bus available. In this case both are bus 0.

This patch saves quite some time during guest kernel boot, as it
prevents from checking each bus for available devices.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-23 19:03:19 +02:00
Sebastien Boeuf
ec56710c9b devices: ioapic: Mask entries by default
When created, the IOAPIC entries should be masked, as it is the guest's
responsibility (FW and/or OS) to unmask them if/when necessary.

This patch saves a full round of port I/O writes from the guest to the
IOAPIC, meant for masking the unmasked entries.

Because they're now masked, the entries are not enabled, which means
they are not connected from a KVM perspective, saving from unneeded
registration/unregistration of the irq fds.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-23 19:03:19 +02:00
Sebastien Boeuf
827810dbd5 ci: Fix virtiofsd build by staying on older branch
While we figure out the details on how to correctly build virtiofsd from
the latest rebase from the branch "virtio-fs-dev" (which now relies on
QEMU's new build system), let's fix the CI by relying on an older branch
which still relies on the previous build system.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-23 17:06:34 +01:00
Henry Wang
c85c1f0d76 ci: AArch64: enable snapshot/restore integration test case
Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
961c5f2cb2 vmm: AArch64: enable VM states save/restore for AArch64
The states of GIC should be part of the VM states. This commit
enables the AArch64 VM states save/restore by adding save/restore
of GIC states.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
7c40a78b66 arch: Fix wrong trial of creating GICv3-ITS for non-PCI use cases
Currently for AArch64, the GICv3-ITS is tried to be created first
when PCI is not needed, which is unnecessary. This commit fixes
the problem.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
3ea4a0797d vmm: seccomp: unify AArch64 and x86_64 FTRUNCATE syscall
The definition of libc::SYS_ftruncate on AArch64 is different
from that on x86_64. This commit unifies the previously hard-coded
syscall number for AArch64.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
48544e4e82 vmm: seccomp: whitelist KVM_GET_REG_LIST in seccomp
`KVM_GET_REG_LIST` ioctl is needed in save/restore AArch64 vCPU.
Therefore we whitelist this ioctl in seccomp.

Also this commit unifies the `SYS_FTRUNCATE` syscall for x86_64
and AArch64.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
c6b47d39e0 vmm: refactor vCPU save/restore code in restoring VM
Similarly as the VM booting process, on AArch64 systems,
the vCPUs should be created before the creation of GIC. This
commit refactors the vCPU save/restore code to achieve the
above-mentioned restoring order.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
970a5a410d vmm: decouple vCPU init from configure_vcpus
Since calling `KVM_GET_ONE_REG` before `KVM_VCPU_INIT` will
result in an error: Exec format error (os error 8). This commit
decouples the vCPU init process from `configure_vcpus`. Therefore
in the process of restoring the vCPUs, these vCPUs can be
initialized separately before started.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
47e65cd341 vmm: AArch64: add methods to get saved vCPU states
The construction of `GICR_TYPER` register will need vCPU states.
Therefore this commit adds methods to extract saved vCPU states
from the cpu manager.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
381d0b4372 devices: remove the migration traits for the Gic struct
Unlike x86_64, the "interrupt_controller" in the device manager
for AArch64 is only a `Gic` object that implements the
`InterruptController` to provide the interrupt delivery service.
This is not the real GIC device so that we do not need to save
its states. Also, we do not need to insert it to the device_tree.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
39c9583b48 arch: AArch64: implement save/restore for GICv3
This commit implements the save/restore for GICv3.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
7ddcad1d8b arch: AArch64: add a field gicr_typers for GIC implementations
The value of GIC register `GICR_TYPER` is needed in restoring
the GIC states. This commit adds a field in the GIC device struct
and a method to construct its value.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
dcf6d9d731 device_manager: AArch64: add a field to set/get GIC device entity
In AArch64 systems, the state of GIC device can only be
retrieved from `KVM_GET_DEVICE_ATTR` ioctl. Therefore to implement
saving/restoring the GIC states, we need to make sure that the
GIC object (either the file descriptor or the device itself) can
be extracted after the VM is started.

This commit refactors the code of GIC creation by adding a new
field `gic_device_entity` in device manager and methods to set/get
this field. The GIC object can be therefore saved in the device
manager after calling `arch::configure_system`.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
e7acbcc184 arch: AArch64: support saving RDIST pending tables into guest RAM
This commit adds a function which allows to save RDIST pending
tables to the guest RAM, as well as unit test case for it.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
29ce3076c2 tests: AArch64: Add unit test cases for accessing GIC registers
This commit adds the unit test cases for getting/setting the GIC
distributor, redistributor and ICC registers.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
09d53aad11 arch: AArch64: Porting GIC icc_regs implementation
This commit ports the implementation of GIC ICC registers
from Firecracker.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
bfde6977c8 arch: AArch64: Porting GIC redist_regs implementation
This commit ports the implementation of GIC redistributor registers
from Firecracker.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
f53990c7e7 arch: AArch64: Porting GIC dist_regs implementation
This commit ports the implementation of GIC distributor registers
from Firecracker.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
89a6b63e6e hypervisor: Implement get_device_attr method for AArch64
This commit implements the `get_device_attr` method for the
`KVM_GET_DEVICE_ATTR` ioctl. This ioctl will be used in retrieving
the GIC status.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
b1285cf528 arch: AArch64: move GIC implementations to a separate module
This commit moves the GIC-related code to a separate module.
Therefore the implementation of GIC registers can be introduced
to the new module.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
9dd188a8e8 tests: AArch64: Add unit test cases for vCPU save/restore
Adds 3 more unit test cases for AArch64:

*save_restore_core_regs
*save_restore_system_regs
*get_set_mpstate

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
ffafeda4b6 AArch64: Implement AArch64 vCPU states save/restore
This commit adds methods to save/restore AArch64 vCPU registers,
including:

1. The AArch64 `VcpuKvmState` structure.

2. Some `Vcpu` trait methods of the `KvmVcpu` structure to
enable the save/restore of the AArch64 vCPU states.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Henry Wang
e3d45be6f7 AArch64: Preparation for vCPU save/restore
This commit ports code from firecracker and refactors the existing
AArch64 code as the preparation for implementing save/restore
AArch64 vCPU, including:

1. Modification of `arm64_core_reg` macro to retrive the index of
arm64 core register and implemention of a helper to determine if
a register is a system register.

2. Move some macros and helpers in `arch` crate to the `hypervisor`
crate.

3. Added related unit tests for above functions and macros.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-09-23 12:37:25 +01:00
Josh Soref
5c3f4dbe6f ch: Fix various misspelled words
Misspellings were identified by https://github.com/marketplace/actions/check-spelling
* Initial corrections suggested by Google Sheets
* Additional corrections by Google Chrome auto-suggest
* Some manual corrections

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2020-09-23 08:59:31 +01:00
Jiangbo Wu
22a2a99e5f acpi: Add hotplug numa node
virtio-mem device would use 'VIRTIO_MEM_F_ACPI_PXM' to add memory to NUMA
node, which MUST be existed, otherwise it will be assigned to node id 0,
even if user specify different node id.

According ACPI spec about Memory Affinity Structure, system hardware
supports hot-add memory region using 'Hot Pluggable | Enabled' flags.

Signed-off-by: Jiangbo Wu <jiangbo.wu@intel.com>
2020-09-22 13:11:39 +02:00
Jiangbo Wu
223189c063 mm: Apply zone's property instread of global config
Apply memory zone's property for associated virtio-mem regions.

Signed-off-by: Jiangbo Wu <jiangbo.wu@intel.com>
2020-09-22 09:56:37 +02:00
Jiangbo Wu
80be8ac0dc mm: Apply memory policy for virtio-mem region
Use zone.host_numa_node to create memory zone, so that memory zone
can apply memory policy in according with host numa node ID

Signed-off-by: Jiangbo Wu <jiangbo.wu@intel.com>
2020-09-22 09:56:37 +02:00
dependabot-preview[bot]
097ba3b191 build(deps): bump hermit-abi from 0.1.15 to 0.1.16
Bumps [hermit-abi](https://github.com/hermitcore/libhermit-rs) from 0.1.15 to 0.1.16.
- [Release notes](https://github.com/hermitcore/libhermit-rs/releases)
- [Commits](https://github.com/hermitcore/libhermit-rs/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-22 06:00:35 +00:00
Sebastien Boeuf
7c346c3844 vmm: Kill vhost-user self-spawned process on failure
If after the creation of the self-spawned backend, the VMM cannot create
the corresponding vhost-user frontend, the VMM must kill the freshly
spawned process in order to ensure the error propagation can happen.

In case the child process would still be around, the VMM cannot return
the error as it waits onto the child to terminate.

This should help us identify when self-spawned failures are caused by a
connection being refused between the VMM and the backend.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-18 17:26:25 +01:00
Rob Bradford
198bd55122 build, release-notes.md: Document 0.10.0 release
Update release notes and version number for the new release.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-18 14:06:10 +01:00
Sebastien Boeuf
555c5c5d9c vmm: Add missing syscalls to signal thread
When the VMM is terminated by receiving a SIGTERM signal, the signal
handler thread must be able to invoke ioctl(TCGETS) and ioctl(TCSETS)
without error.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-18 13:40:10 +01:00
Rob Bradford
41a9b1adef vmm: Add missing syscall to vCPU thread
Fixes: #1717

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-18 13:40:10 +01:00
Rob Bradford
036c2e5e45 Jenkinsfile: Remove "Build" steps from Jenkinsfile
Build testing of changes happens on GitHub actions and the integration
tests will build the binary (with different feature flags) again. So
these earlier build operations are just wasted time on the critical
path.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-18 12:48:30 +01:00
Rob Bradford
66352b100f README: Reference the aarch64 tracking issue.
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-18 10:25:04 +01:00
Rob Bradford
8589d3f985 README: Fix missing punctuation
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-18 10:25:04 +01:00
Rob Bradford
5d535853f4 README: Update table of contents
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-18 10:25:04 +01:00
Rob Bradford
98bce5e044 README: Standardise project nomenclature
Only use `cloud-hypervisor` when referring to the binary itself and
prefer Cloud Hypervisor when referring to the project.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-18 10:25:04 +01:00
Rob Bradford
ce6353818f README: Update status section
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-18 10:25:04 +01:00
Rob Bradford
ea44d0a433 README: Include bzImage as a supported direct kernel boot method
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-18 10:25:04 +01:00
Rob Bradford
6d0b05c6b3 README: Update operating system and architecture support statements
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-18 10:25:04 +01:00
Rob Bradford
ab80789747 README: Configurable hotplug is no longer an objective
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-18 10:25:04 +01:00
Rob Bradford
5506908199 README: Remove KVM exclusivity
With our hypervisor crate we are no aiming to be KVM exclusive.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-18 10:25:04 +01:00
Rob Bradford
b666d40f9d README: Remove security reporting guidelines
These guidelines are no longer correct remove them as they are
unhelpful.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-18 10:25:04 +01:00
Rob Bradford
f0fae3e8b6 README: Remove pre-production disclaimer
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-18 10:25:04 +01:00
Sebastien Boeuf
b8bbe244b7 block_util: Ensure all io_uring operations are asynchronous
Some operations complete directly after they have been submitted, which
means they are not submitted asynchronously and therefore they don't
generate any ioevent. This is the reason why we are not processing some
of the completed operations, which leads to some unpredictable
behaviors.

Forcing all io_uring operations submitted to the SQE to be asynchronous
helps simplifying the code as it ensures the completion of every
operation will generate an ioevent, therefore no operation is missed.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-17 23:16:27 +02:00
dependabot-preview[bot]
144f0839ae build(deps): bump cc from 1.0.59 to 1.0.60
Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.59 to 1.0.60.
- [Release notes](https://github.com/alexcrichton/cc-rs/releases)
- [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.59...1.0.60)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-17 07:43:00 +00:00
Sebastien Boeuf
5a3d54fa19 ci: Extend virtio-mem integration test with reboot
Now that virtio-mem supports reboot, we extend the existing integration
tests to validate the amount of RAM after reboot is the same as before
the reboot, but also that we can still resize down the VM or the memory
zone after the reboot.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
46d972e402 virtio-devices: mem: Add missing syscall to seccomp filters
The missing syscall rt_sigprocmask(2) was triggered for the musl build
upon rebooting the VM, and was causing the VM to be killed.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
87bb041101 resources: x86_64: Enable auto onlining of memory blocks
In order to facilitate the memory hotplug for our users, let's enable
the automatic memory onlining in our guest kernel by activating the
kernel config option 'CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE'.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
1e1a50ef70 vmm: Update memory configuration upon virtio-mem resizing
Based on all the preparatory work achieved through previous commits,
this patch updates the 'hotplugged_size' field for both MemoryConfig and
MemoryZoneConfig structures when either the whole memory is resized, or
simply when a memory zone is resized.

This fixes the lack of support for rebooting a VM with the right amount
of memory plugged in.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
de2b917f55 vmm: Add hotplugged_size to VirtioMemZone
Adding a new field to VirtioMemZone structure, as it lets us associate
with a particular virtio-mem region the amount of memory that should be
plugged in at boot.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
3faf8605f3 vmm: Group virtio-mem fields under a dedicated structure
This patch simplifies the code as we have one single Option for the
VirtioMemZone. This also prepares for storing additional information
related to the virtio-mem region.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
4e1b78e1ff vmm: Add 'hotplugged_size' to memory parameters
Add the new option 'hotplugged_size' to both --memory-zone and --memory
parameters so that we can let the user specify a certain amount of
memory being plugged at boot.

This is also part of making sure we can store the virtio-mem size over a
reboot of the VM.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Hui Zhu
33a1e37c35 virtio-devices: mem: Allow for an initial size
This commit gives the possibility to create a virtio-mem device with
some memory already plugged into it. This is preliminary work to be
able to reboot a VM with the virtio-mem region being already resized.

Signed-off-by: Hui Zhu <teawater@antfin.com>
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
8b5202aa5a vmm: Always add virtio-mem region upon VM creation
Now that e820 tables are created from the 'boot_guest_memory', we can
simplify the memory manager code by adding the virtio-mem regions when
they are created. There's no need to wait for the first hotplug to
insert these regions.

This also anticipates the need for starting a VM with some memory
already plugged into the virtio-mem region.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
66fc557015 vmm: Store boot guest memory and use it for boot sequence
In order to differentiate the 'boot' memory regions from the virtio-mem
regions, we store what we call 'boot_guest_memory'. This is useful to
provide the adequate list of regions to the configure_system() function
as it expects only the list of regions that should be exposed through
the e820 table.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
9d8672afc6 ci: Extend guest NUMA integration test with memory zone resizing
Extend the existing test to validate that each NUMA node gets assigned
the right amount of memory after each memory zone has been resized.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
5823c12eab ci: Extend memory zone integration test with 'resize-zone'
Now that we can resize each memory zone independently, this commit
extends the memory zone related test by validating 'vm.resize-zone'
works correctly.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
1798ed8194 vmm: virtio-mem: Enforce alignment and size requirements
The virtio-mem driver is generating some warnings regarding both size
and alignment of the virtio-mem region if not based on 128MiB:

The alignment of the physical start address can make some memory
unusable.
The alignment of the physical end address can make some memory
unusable.

For these reasons, the current patch enforces virtio-mem regions to be
128MiB aligned and checks the size provided by the user is a multiple of
128MiB.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
eb7b923e22 vmm: Create virtio-mem device with appropriate NUMA node
Now that virtio-mem device accept a guest NUMA node as parameter, we
retrieve this information from the list of NUMA nodes. Based on the
memory zone associated with the virtio-mem device, we obtain the NUMA
node identifier, which we provide to the virtio-mem device.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
dcedd4cded virtio-devices: virtio-mem: Add NUMA support
Implement support for associating a virtio-mem device with a specific
guest NUMA node, based on the ACPI proximity domain identifier.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
0658559880 vmm: memory_manager: Rename 'use_zones' with 'user_provided_zones'
This brings more clarity on the meaning of this boolean.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
775f3346e3 vmm: Rename 'virtiomem' to 'virtio_mem'
For more consistency and help reading the code better, this commit
renames all 'virtiomem*' variables into 'virtio_mem*'.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
bc1bbb6dc4 virtio-devices: virtio-mem: Add missing syscalls
By testing manually the memory resizing through virtio-mem, several
missing syscalls have been identified.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
015c78411e vmm: Add a 'resize-zone' action to the API actions
Implement a new VM action called 'resize-zone' allowing the user to
resize one specific memory zone at a time. This relies on all the
preliminary work from the previous commits to resize each virtio-mem
device independently from each others.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
141df701dd vmm: memory_manager: Make virtiomem_resize function generic
By adding a new parameter 'id' to the virtiomem_resize() function, we
prepare this function to be usable for both global memory resizing and
memory zone resizing.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
34331d3e72 vmm: memory_manager: Fix virtio-mem resize
It's important to return the region covered by virtio-mem the first time
it is inserted as the device manager must update all devices with this
information.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
adc59a6f15 vmm: memory_manager: Create one virtio-mem per memory zone
Based on the previous code changes, we can now update the MemoryManager
code to create one virtio-mem region and resizing handler per memory
zone. This will naturally create one virtio-mem device per memory zone
from the DeviceManager's code which has been previously updated as well.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
c645a72c17 vmm: Add 'hotplug_size' to memory zones
In anticipation for resizing support of an individual memory zone,
this commit introduces a new option 'hotplug_size' to '--memory-zone'
parameter. This defines the amount of memory that can be added through
each specific memory zone.

Because memory zone resize is tied to virtio-mem, make sure the user
selects 'virtio-mem' hotplug method, otherwise return an error.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
30ff7e108f vmm: Prepare code to accept multiple virtio-mem devices
Both MemoryManager and DeviceManager are updated through this commit to
handle the creation of multiple virtio-mem devices if needed. For now,
only the framework is in place, but the behavior remains the same, which
means only the memory zone created from '--memory' generates a
virtio-mem region that can be used for resize.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Sebastien Boeuf
b173b6c5b4 vmm: Create a MemoryZone structure
In order to anticipate the need for storing memory regions along with
virtio-mem information for each memory zone, we create a new structure
MemoryZone that will replace Vec<Arc<GuestRegionMmap>> in the hash map
MemoryZones.

This makes thing more logical as MemoryZones becomes a list of
MemoryZone sorted by their identifier.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 19:20:04 +02:00
Rob Bradford
27c28fa3b0 vmm, arch: Enable KVM HyperV support
Inject CPUID leaves for advertising KVM HyperV support when the
"kvm_hyperv" toggle is enabled. Currently we only enable a selection of
features required to boot.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-16 16:08:01 +01:00
Rob Bradford
da642fcf7f hypervisor: Add "HyperV" exit to list of KVM exits
Currently we don't need to do anything to service these exits but when
the synthetic interrupt controller is active an exit will be triggered
to notify the VMM of details of the synthetic interrupt page.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-16 16:08:01 +01:00
Rob Bradford
9b48ee38cb hypervisor: Support enabling HyperV synthetic interrupt controller
This adds a KVM HyperV synthetic interrupt controller in place of the
emulated PIC.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-16 16:08:01 +01:00
Rob Bradford
5495ab7415 vmm: Add "kvm_hyperv" toggle to "--cpus"
This turns on the KVM HyperV emulation.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-16 16:08:01 +01:00
Rob Bradford
c03dbe8cc7 virtio-devices: block: Support multiple data descriptors
The Windows virtio block driver puts multiple data descriptors between
the header and the status footer. To handle this when parsing iterate
over the descriptor chain until the end is reached accumulating the
address and length pairs in a vector. For execution iterate over the
vector and make sequential reads from the disk for each data descriptor.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 16:13:24 +02:00
Sebastien Boeuf
5f6432830c block_util: io_uring: Move to vectored I/O
In anticipation for supporting multiple virtio descriptors, let's make
sure the read/write operations are performed with vectored I/O.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 16:13:24 +02:00
Sebastien Boeuf
b3435d51d9 vmm: cpu: Add missing io_uring syscalls to vCPU threads
Some of the io_uring setup happens upon activation of the virtio-blk
device, which is initially triggered through an MMIO VM exit. That's why
the vCPU threads must authorize io_uring related syscalls.

This commit ensures the virtio-blk io_uring implementation can be used
along with the seccomp filters enabled.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-16 11:59:47 +02:00
dependabot-preview[bot]
3d7e7d3869 build(deps): bump kvm-ioctls from f5312ea to 6442739
Bumps [kvm-ioctls](https://github.com/cloud-hypervisor/kvm-ioctls) from `f5312ea` to `6442739`.
- [Release notes](https://github.com/cloud-hypervisor/kvm-ioctls/releases)
- [Commits](f5312ea173...64427395b6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-15 16:47:55 +00:00
dependabot-preview[bot]
ae35967f02 build(deps): bump syn from 1.0.40 to 1.0.41
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.40 to 1.0.41.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.40...1.0.41)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-14 17:16:43 +00:00
dependabot-preview[bot]
1ab12c47b6 build(deps): bump serde from 1.0.115 to 1.0.116
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.115 to 1.0.116.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.115...v1.0.116)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-14 06:52:01 +00:00
dependabot-preview[bot]
701f3ae475 build(deps): bump miniz_oxide from 0.4.1 to 0.4.2
Bumps [miniz_oxide](https://github.com/Frommi/miniz_oxide) from 0.4.1 to 0.4.2.
- [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.4.1...0.4.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-14 05:54:50 +00:00
dependabot-preview[bot]
a3bf981b94 build(deps): bump serde_derive from 1.0.115 to 1.0.116
Bumps [serde_derive](https://github.com/serde-rs/serde) from 1.0.115 to 1.0.116.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.115...v1.0.116)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-14 05:54:33 +00:00
Rob Bradford
bd463324f3 build: Move to rust-vmm vhost crate
There is no need to point at our forked version any longer.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-11 13:43:57 +02:00
Bo Chen
b4f6db5f31 virtio-devices: vsock: Add 'brk' to the seccomp list
We observed CI instability for the past couple of days. This
instability is confirmed to be a result of incomplete seccomp
filters. Given the filter on 'virtio_vsock' is recently added and
is missing 'brk', it is likely to be the root cause of the
instability.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-11 07:56:52 +02:00
Bo Chen
9682d74763 vmm: seccomp: Add seccomp filters for signal_handler worker thread
This patch covers the last worker thread with dedicated secomp filters.

Fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-11 07:42:31 +02:00
Bo Chen
2612a6df29 vmm: seccomp: Add seccomp filters for the vcpu worker thread
Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-11 07:42:31 +02:00
Rob Bradford
d793cc4da3 vmm: device_manager: Extract common PCI code
Extract common code for adding devices to the PCI bus into its own
function from the VFIO and VIRTIO code paths.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-11 07:33:18 +02:00
dependabot-preview[bot]
cd8c38384e build(deps): bump getrandom from 0.1.14 to 0.1.15
Bumps [getrandom](https://github.com/rust-random/getrandom) from 0.1.14 to 0.1.15.
- [Release notes](https://github.com/rust-random/getrandom/releases)
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/getrandom/compare/v0.1.14...v0.1.15)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-10 11:53:56 +00:00
Rob Bradford
15025d71b1 devices, vm-device: Move BusDevice and Bus into vm-device
This removes the dependency of the pci crate on the devices crate which
now only contains the device implementations themselves.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-10 09:35:38 +01:00
dependabot-preview[bot]
f24a12913a build(deps): bump libc from 0.2.76 to 0.2.77
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.76 to 0.2.77.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.76...0.2.77)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-10 06:45:09 +00:00
dependabot-preview[bot]
7fddb9aa4f build(deps): bump proc-macro2 from 1.0.20 to 1.0.21
Bumps [proc-macro2](https://github.com/alexcrichton/proc-macro2) from 1.0.20 to 1.0.21.
- [Release notes](https://github.com/alexcrichton/proc-macro2/releases)
- [Commits](https://github.com/alexcrichton/proc-macro2/compare/1.0.20...1.0.21)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-09 22:28:52 +01:00
Bo Chen
3c923f0727 virtio-devices: seccomp: Add seccomp filters for virtio_vsock thread
This patch enables the seccomp filters for the virtio_vsock worker
thread.

Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-09 17:04:39 +01:00
Bo Chen
1175fa2bc7 virtio-devices: seccomp: Add seccomp filters for blk_io_uring thread
This patch enables the seccomp filters for the block_io_uring worker
thread.

Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-09 17:04:39 +01:00
Sebastien Boeuf
56b0c85578 ci: Introduce SGX integration testing
Extending the Cloud-Hypervisor CI to allow for testing SGX on a
dedicated machine where special image and kernels are ready.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-09 15:33:49 +02:00
Rob Bradford
a86a2711f8 ch-remote: Support using unit suffices for "resize"
Remove the requirement for the user to calculate the size they want in
bytes.

Fixes: #1596

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-08 22:27:34 +02:00
Rob Bradford
42de27b215 virtio-devices: Remove virtio_pausable! macros
These are no longer needed as virtio device pausing is handledby
VirtioCommon.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-07 17:39:30 +02:00
Rob Bradford
a641f8930f virtio-devices: virtio-vsock: Port to VirtioCommon
Use VirtioCommon to handle activate() preparation, reset() and Pausable.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-07 17:39:30 +02:00
Rob Bradford
12f90569e2 virtio-devices: vhost-user-net: Port to VirtioCommon
Use VirtioCommon to handle activate() preparation, reset() and Pausable.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-07 17:39:30 +02:00
Rob Bradford
d33a1a5313 virtio-devices: vhost-user-fs: Port to VirtioCommon
Use VirtioCommon to handle activate() preparation, reset() and Pausable.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-07 17:39:30 +02:00
Rob Bradford
1e4b612d39 virtio-devices: vhost-user-block: Port to VirtioCommon
Use VirtioCommon to handle activate() preparation, reset() and Pausable.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-07 17:39:30 +02:00
Wei Liu
53f4fed516 hypervisor: drop get_api_version from Hypervisor trait
The new function already checks if the API version is compatible. There
is no need to expose the get_api_version function to code outside
hypervisor crate.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-09-07 11:59:08 +01:00
Wei Liu
d73971e407 hypervisor: kvm: check API compatibility
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-09-07 11:59:08 +01:00
Bo Chen
559d1840d8 build: Use the crate version when the 'git describe' command failed
In our build-script (build.rs), we won't set the environment variable
'BUILD_VERSION' when the 'git describe' command failed (e.g. when the
current source tree does not contain git information). This patch added
a fall back path where the default value of 'BUILD_VERSION' is based on
the 'cloud-hypervisor' crate version.

Fixes: #1669

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-07 12:03:57 +02:00
dependabot-preview[bot]
318ad83509 build(deps): bump syn from 1.0.39 to 1.0.40
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.39 to 1.0.40.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.39...1.0.40)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-07 05:39:02 +00:00
Sebastien Boeuf
e15dba2925 vmm: Rename NUMA option 'id' into 'guest_numa_id'
The goal of this commit is to rename the existing NUMA option 'id' with
'guest_numa_id'. This is done without any modification to the way this
option behaves.

The reason for the rename is caused by the observation that all other
parameters with an option called 'id' expect a string to be provided.

Because in this particular case we expect a u32 representing a proximity
domain from the ACPI specification, it's better to name it with a more
explicit name.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-07 07:37:14 +02:00
Sebastien Boeuf
55e9827e00 docs: Update memory documentation
Based on the recent changes regarding how to describe NUMA nodes to the
guest, the documentation related to memory zones and NUMA has been
updated accordingly.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-07 07:37:14 +02:00
Sebastien Boeuf
bf5e028016 ci: Update memory zone and NUMA integration tests
Since both --memory-zone and --numa parameters have been updated with
addition and removal of multiple options, this commit updates the
related integration tests to ensure they are still valid.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-07 07:37:14 +02:00
Sebastien Boeuf
1970ee89da main, vmm: Remove guest_numa_node option from memory zones
The way to describe guest NUMA nodes has been updated through previous
commits, letting the user describe the full NUMA topology through the
--numa parameter (or NumaConfig).

That's why we can remove the deprecated and unused 'guest_numa_node'
option.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-07 07:37:14 +02:00
Sebastien Boeuf
f21c04166a vmm: Move NUMA node list creation to Vm structure
Based on the previous changes introducing new options for both memory
zones and NUMA configuration, this patch changes the behavior of the
NUMA node definition. Instead of relying on the memory zones to define
the guest NUMA nodes, everything goes through the --numa parameter. This
allows for defining NUMA nodes without associating any particular memory
range to it. And in case one wants to associate one or multiple memory
ranges to it, the expectation is to describe a list of memory zone
through the --numa parameter.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-07 07:37:14 +02:00
Sebastien Boeuf
dc42324351 vmm: Add 'memory_zones' option to NumaConfig
This new option provides a new way to describe the memory associated
with a NUMA node. This is the first step before we can remove the
'guest_numa_node' option from the --memory-zone parameter.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-07 07:37:14 +02:00
Sebastien Boeuf
5d7215915f vmm: memory_manager: Store a list of memory zones
Now that we have an identifier per memory zone, and in order to keep
track of the memory regions associated with the memory zones, we create
and store a map referencing list of memory regions per memory zone ID.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-07 07:37:14 +02:00
Sebastien Boeuf
3ff82b4b65 main, vmm: Add mandatory id to memory zones
In anticipation for allowing memory zones to be removed, but also in
anticipation for refactoring NUMA parameter, we introduce a mandatory
'id' option to the --memory-zone parameter.

This forces the user to provide a unique identifier for each memory zone
so that we can refer to these.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-07 07:37:14 +02:00
Rob Bradford
c37fb5b602 virtio-devices: rng: Port to VirtioCommon
Use VirtioCommon to handle activate() preparation, reset() and Pausable.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-05 10:06:39 +01:00
Rob Bradford
d5d0b8566b virtio-devices: pmem: Port to VirtioCommon
Use VirtioCommon to handle activate() preparation, reset() and Pausable.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-05 10:06:39 +01:00
Rob Bradford
30f4f2b9ab virtio-devices: net: Port to VirtioCommon
Use VirtioCommon to handle activate() preparation, reset() and Pausable.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-05 10:06:39 +01:00
Rob Bradford
df8a55ab11 virtio-devices: mem: Port to VirtioCommon
Use VirtioCommon to handle activate() preparation, reset() and Pausable.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-05 10:06:39 +01:00
Rob Bradford
376babb21e virtio-devices: iommu: Port to VirtioCommon
Use VirtioCommon to handle activate() preparation, reset() and Pausable.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-05 10:06:39 +01:00
Rob Bradford
f6b75c683f virtio-devices: console: Port to VirtioCommon
Use VirtioCommon to handle activate() preparation, reset() and Pausable.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-05 10:06:39 +01:00
Rob Bradford
360d6702b6 virtio-devices: block_io_uring: Port to VirtioCommon
Use VirtioCommon to handle activate() preparation, reset() and Pausable.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-05 10:06:39 +01:00
Rob Bradford
3c6fd5634d virtio-devices: balloon: Port to VirtioCommon
Use VirtioCommon to handle activate() preparation, reset() and Pausable.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-05 10:06:39 +01:00
Rob Bradford
3487524950 virtio-device: block, common: Split out common code
Split the block device implementation into code that be used in common
between multiple different virtio device implementations.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-05 10:06:39 +01:00
Rob Bradford
a9a138460b virtio-devices: Use Default::default() for transitioning to VirtioCommon
In order to simplify the transition to VirtioCommon and to avoid needing
to set empty fields derive Default for VirtioCommon.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-05 10:06:39 +01:00
Rob Bradford
008cf4a5ae virtio-devices: block: Rearrange activate() to match other devices
Rearrange the code to match other devices which makes it easier to prep
for sharing this between other devices.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-05 10:06:39 +01:00
Rob Bradford
56f03db69c virtio-devices: net: Simplify activate function
Move the if-let for the taps later which makes the earlier activation
code identical to other devices.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-05 10:06:39 +01:00
Rob Bradford
31d7712878 virtio-devices: block: Remove duplicated block
The same block of code seems to copied twice into the block activation
function.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-05 10:06:39 +01:00
Samuel Ortiz
e5ce6dc43c vmm: cpu: Warn if the guest is trying to access unregistered IO ranges
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-09-04 14:39:58 +02:00
dependabot-preview[bot]
7f2ee1f984 build(deps): bump libz-sys from 1.1.1 to 1.1.2
Bumps [libz-sys](https://github.com/rust-lang/libz-sys) from 1.1.1 to 1.1.2.
- [Release notes](https://github.com/rust-lang/libz-sys/releases)
- [Commits](https://github.com/rust-lang/libz-sys/compare/1.1.1...1.1.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-04 05:41:22 +00:00
dependabot-preview[bot]
4870b5099a build(deps): bump proc-macro2 from 1.0.19 to 1.0.20
Bumps [proc-macro2](https://github.com/alexcrichton/proc-macro2) from 1.0.19 to 1.0.20.
- [Release notes](https://github.com/alexcrichton/proc-macro2/releases)
- [Commits](https://github.com/alexcrichton/proc-macro2/compare/1.0.19...1.0.20)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-04 05:41:03 +00:00
Bo Chen
4392a1484c tests: Port test_bzimage_reboot to the new methodology
Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-03 17:47:14 +01:00
Bo Chen
ded376c6e1 tests: Port test_console_file to the new methodology
Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-03 17:47:14 +01:00
Bo Chen
a4abb7f8e5 tests: Port test_virtio_console to the new methodology
Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-03 17:47:14 +01:00
Bo Chen
aac0cba0d1 tests: Port test_serial_file to the new methodology
Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-03 17:47:14 +01:00
Bo Chen
9686aef2c9 tests: Port test_serial_tty to the new methodology
Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-03 17:47:14 +01:00
Bo Chen
4e0e3d6221 tests: Port test_serial_null to the new methodology
Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-03 17:47:14 +01:00
Rob Bradford
4bb00224b4 virtio-devices: balloon: Port to VirtioCommon for feature handling
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-03 17:00:32 +02:00
Rob Bradford
dc9f1e4cdf virtio-devices: block_io_uring: Port to VirtioCommon for feature handling
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-03 17:00:32 +02:00
Rob Bradford
e3abcdbff8 virtio-devices: console: Port to VirtioCommon for feature handling
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-03 17:00:32 +02:00
Rob Bradford
9fc8b6d242 virtio-devices: iommu: Port to VirtioCommon for feature handling
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-03 17:00:32 +02:00
Rob Bradford
d63dcae233 virtio-devices: mem: Port to VirtioCommon for feature handling
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-03 17:00:32 +02:00
Rob Bradford
47c165e08a virtio-devices: net: Port to VirtioCommon for feature handling
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-03 17:00:32 +02:00
Rob Bradford
84b4aef87a virtio-devices: pmem: Port to VirtioCommon for feature handling
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-03 17:00:32 +02:00
Rob Bradford
37e99bbbb0 virtio-devices: rng: Port to VirtioCommon for feature handling
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-03 17:00:32 +02:00
Rob Bradford
edb7ac5922 virtio-devices: vhost-user-block: Port to VirtioCommon for feature handling
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-03 17:00:32 +02:00
Rob Bradford
8c42dd3811 virtio-devices: vhost-user-fs: Port to VirtioCommon for feature handling
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-03 17:00:32 +02:00
Rob Bradford
9d0ebf8d25 virtio-devices: vhost-user-net: Port to VirtioCommon for feature handling
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-03 17:00:32 +02:00
Rob Bradford
684b47013a virtio-devices: vsock: Port to VirtioCommon for feature handling
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-03 17:00:32 +02:00
Rob Bradford
be945b3bc8 virtio-devices: block: Port to VirtioCommon for feature handling
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-03 17:00:32 +02:00
Rob Bradford
081c897989 virtio-devices: Introduce VirtioCommon for shared functionality
Introduce VirtioCommon to help remove duplicated functionality and state
between implementations of VirtioDevice. Initially it is only handling
feature acknowledgement and testing.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-03 17:00:32 +02:00
Bo Chen
9e7e64d2a3 tests: Port various integration tests to new methodology
This patch ported many tests to the new methodology, where the guest log
will be printed only when the test is failing.

Things to finish in follow-up PRs:

1. Special tests not ported yet include: test_reboot,
test_bzimage_reboot, test_serial_null(), test_serial_tty(),
test_serial_file(), test_virtio_console(), test_console_file(),
and test_simple_launch.

2. Few direct calls to 'Command::new(clh_command("cloud-hypervisor"))',
which is still printing the guest console

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-09-03 08:13:20 +02:00
Rob Bradford
c266e56a02 hypervisor: Fix copy and pasted error enum entries
Remove unused GetNrVcpus error and fix duplicated error message for
GetCpuId.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-02 10:24:48 -07:00
Sebastien Boeuf
239169ad1d docs: Add documentation about memory in Cloud-Hypervisor
Writing some new documentation to help users understand how the guest
memory can be described through Cloud-Hypervisor parameters.

Fixes #1659

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-02 13:46:28 +02:00
Rob Bradford
dac600305b vm-virtio: queue: Clear all queue fields on reset
Some of the fields on the queue were not being cleared up on device
reset.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-09-02 11:48:44 +01:00
Sebastien Boeuf
5d80bc2339 ci: Add distance validation to NUMA integration test
By extending the existing NUMA integration test, this commit validates
the proper distances between NUMA nodes are exposed to the guest.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-01 18:09:01 +02:00
Sebastien Boeuf
c0d0d23932 vmm: acpi: Introduce SLIT for NUMA nodes distances
By introducing the SLIT (System Locality Distance Information Table), we
provide the guest with the distance between each node. This lets the
user describe the NUMA topology with a lot of details so that slower
memory backing the VM can be exposed as being further away from other
nodes.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-01 18:09:01 +02:00
Sebastien Boeuf
9548e7e857 vmm: Update NUMA node distances internally
Based on the NumaConfig which now provides distance information, we can
internally update the list of NUMA nodes with the exact distances they
should be located from other nodes.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-01 18:09:01 +02:00
Sebastien Boeuf
a5a29134ca vmm: Extend --numa parameter with NUMA node distances
By introducing 'distances' option, we let the user describe a list of
destination NUMA nodes with their associated distances compared to the
current node (defined through 'id').

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-01 18:09:01 +02:00
Sebastien Boeuf
d6fc18da9e ci: Add CPUs validation to the NUMA integration test
Extend the existing NUMA integration to validate that specifying CPUs
for each NUMA node gets propagated to the guest.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-01 15:25:00 +02:00
Sebastien Boeuf
629befdb4a vmm: acpi: Add CPUs to NUMA nodes
Based on the list of CPUs related to each NUMA node, Processor Local
x2APIC Affinity structures are created and included into the SRAT table.

This describes which CPUs are part of each node.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-01 15:25:00 +02:00
Sebastien Boeuf
db28db8567 vmm: Update NUMA nodes based on NumaConfig
Relying on the list of CPUs defined through the NumaConfig, this patch
will update the internal list of CPUs attached to each NUMA node.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-01 15:25:00 +02:00
Sebastien Boeuf
42f963d6f2 main, vmm: Add new --numa parameter
Through this new parameter, we give users the opportunity to specify a
set of CPUs attached to a NUMA node that has been previously created
from the --memory-zone parameter.

This parameter will be extended in the future to describe the distance
between multiple nodes.

For instance, if a user wants to attach CPUs 0, 1, 2 and 6 to a NUMA
node, here are two different ways of doing so:
Either
	./cloud-hypervisor ... --numa id=0,cpus=0-2:6
Or
	./cloud-hypervisor ... --numa id=0,cpus=0:1:2:6

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-01 15:25:00 +02:00
Sebastien Boeuf
36171caba9 ci: Add integration test for defining NUMA nodes in the guest
This new test validates the guest OS can find the NUMA nodes which have
been defined by the user through the CLI, and that the right amount of
memory is associated with each node.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-01 14:11:49 +02:00
Sebastien Boeuf
65a23c6fc6 vmm: acpi: Create the SRAT table
The SRAT table (System Resource Affinity Table) is needed to describe
NUMA nodes and how memory ranges and CPUs are attached to them.

For now it simply attaches a list of Memory Affinity structures based on
the list of NUMA nodes created from the VMM.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-01 14:11:49 +02:00
Sebastien Boeuf
cf81254a8d vmm: memory_manager: Create a NUMA node list
Based on the 'guest_numa_node' option, we create and store a list of
NUMA nodes in the MemoryManager. The point being to associate a list of
memory regions to each node, so that we can later create the ACPI tables
with the proper memory range information.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-01 14:11:49 +02:00
Sebastien Boeuf
768dbd1fb0 vmm: Add 'guest_numa_node' option to 'memory-zone'
With the introduction of this new option, the user will be able to
describe if a particular memory zone should belong to a specific NUMA
node from a guest perspective.

For instance, using '--memory-zone size=1G,guest_numa_node=2' would let
the user describe that a memory zone of 1G in the guest should be
exposed as being associated with the NUMA node 2.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-01 14:11:49 +02:00
Sebastien Boeuf
274c001eab vmm: Use u32 instead of u64 for host_numa_node option
Given that ACPI uses u32 as the type for the Proximity Domain, we can
use u32 instead of u64 as the type for 'host_numa_node' option.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-09-01 13:29:42 +02:00
dependabot-preview[bot]
4c6a250383 build(deps): bump kvm-ioctls from 37953e9 to f5312ea
Bumps [kvm-ioctls](https://github.com/cloud-hypervisor/kvm-ioctls) from `37953e9` to `f5312ea`.
- [Release notes](https://github.com/cloud-hypervisor/kvm-ioctls/releases)
- [Commits](37953e968b...f5312ea173)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-31 06:21:24 +00:00
dependabot-preview[bot]
42bfea5d5a build(deps): bump libz-sys from 1.1.0 to 1.1.1
Bumps [libz-sys](https://github.com/rust-lang/libz-sys) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/rust-lang/libz-sys/releases)
- [Commits](https://github.com/rust-lang/libz-sys/commits/1.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-31 06:21:07 +00:00
Michael Zhao
a1c4c77cd8 tests: Enable test cases checking PCI MSI on AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-08-31 08:20:42 +02:00
Michael Zhao
2b8e08bd36 tests: Enable test_multi_cpu case on AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-08-31 08:20:42 +02:00
Michael Zhao
85c9bd0f47 tests: Enable vhost-user-net self-spawned test cases
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-08-31 08:19:23 +02:00
Michael Zhao
23e5a726ec virtio-devices: Add seccomp rules for vhost-user backend
The missing rules caused failures when guest powered off.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-08-31 08:19:23 +02:00
Michael Zhao
a95b6bbd8b vmm: Add seccomp rules for starting vhost-user-net backend on AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-08-31 08:19:23 +02:00
Hui Zhu
f7b3581645 cloud-hypervisor.yaml: MemoryConfig: Add balloon_size
"struct MemoryConfig" has balloon_size but not in MemoryConfig
of cloud-hypervisor.yaml.
This commit adds it.

Signed-off-by: Hui Zhu <teawater@antfin.com>
2020-08-28 09:58:39 +02:00
Hui Zhu
9c257a7e8c aarch64: fdt.rs: create_devices_node: Change sort_by to sort_by_key
Change sort_by to sort_by_key in create_devices_node.

Fixes: #1646

Signed-off-by: Hui Zhu <teawater@antfin.com>
2020-08-28 08:02:54 +02:00
Sebastien Boeuf
a8a9e61c3d vmm: memory_manager: Allow host NUMA for RAM backed files
Let's narrow down the limitation related to mbind() by allowing shared
mappings backed by a file backed by RAM. This leaves the restriction on
only for mappings backed by a regular file.

With this patch, host NUMA node can be specified even if using
vhost-user devices.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-27 08:39:38 -07:00
Sebastien Boeuf
1b4591aecc vmm: memory_manager: Apply NUMA policy to memory zones
Relying on the new option 'host_numa_node' from the 'memory-zone'
parameter, the user can now define which NUMA node from the host
should be used to back the current memory zone.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-27 08:39:38 -07:00
Sebastien Boeuf
e6f585a31c vmm: Add 'host_numa_nodes' option to memory zones
Since memory zones have been introduced, it is now possible for a user
to specify multiple backends for the guest RAM. By adding a new option
'host_numa_node' to the 'memory-zone' parameter, we allow the guest RAM
to be backed by memory that might come from a specific NUMA node on the
host.

The option expects a node identifier, specifying which NUMA node should
be used to allocate the memory associated with a specific memory zone.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-27 08:39:38 -07:00
Sebastien Boeuf
ad5d0e4713 vmm: Remove 'mergeable' from memory zones
The flag 'mergeable' should only apply to the entire guest RAM, which is
why it is removed from the MemoryZoneConfig as it is defined as a global
parameter at the MemoryConfig level.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-27 07:26:49 +02:00
dependabot-preview[bot]
be8f40f2b6 build(deps): bump redox_users from 0.3.4 to 0.3.5
Bumps redox_users from 0.3.4 to 0.3.5.

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-26 21:22:08 +00:00
Sebastien Boeuf
89e7774b96 vmm: openapi: Don't expect cmdline to always be there
The 'cmdline' parameter should not be required as it is not needed when
the 'kernel' parameter is the rust-hypervisor-fw, which means the kernel
and the associated command line will be found from the EFI partition.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-25 16:49:05 +02:00
Sebastien Boeuf
e8149380b7 vmm: memory_manager: Factorize memory regions creation
Factorize the codepath between simple memory and multiple memory zones.
This simplifies the way regions are memory mapped, as everything relies
on the same codepath. This is performed by creating a memory zone on the
fly for the specific use case where --memory is used with size being
different from 0. Internally, the code can rely on memory zones to
create the memory regions forming the guest memory.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-25 16:43:10 +02:00
Sebastien Boeuf
c58dd761f4 vmm: Remove 'file' option from MemoryConfig
After the introduction of user defined memory zones, we can now remove
the deprecated 'file' option from --memory parameter. This makes this
parameter simpler, letting more advanced users define their own custom
memory zones through the dedicated parameter.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-25 16:43:10 +02:00
Sebastien Boeuf
5bf7113768 vmm: memory_manager: Remove restrictions about snapshot/restore
User defined memory regions can now support being snapshot and restored,
therefore this commit removes the restrictions that were applied through
earlier commit.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-25 16:43:10 +02:00
Sebastien Boeuf
2583d572fc vmm: memory_manager: Simplify how to restore memory regions
By factorizing a lot of code into create_ram_region(), this commit
achieves the simplification of the restore codepath. Additionally, it
makes user defined memory zones compatible with snapshot/restore.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-25 16:43:10 +02:00
Sebastien Boeuf
b14c861c6f vmm: memory_manager: Store memory regions content only when necessary
First thing, this patch introduces a new function to identify if a file
descriptor is linked to any hard link on the system. This can let the
VMM know if the file can be accessed by the user, or if the file will
be destroyed as soon as the VMM releases the file descriptor.

Based on this information, and associated with the knowledge about the
region being MAP_SHARED or not, the VMM can now decide to skip the copy
of the memory region content. If the user has access to the file from
the filesystem, and if the file has been mapped as MAP_SHARED, we can
consider the guest memory region content to be present in this file at
any point in time. That's why in this specific case, there's no need for
performing the copy of the memory region content into a dedicated file.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-25 16:43:10 +02:00
Sebastien Boeuf
d1ce52f3a8 vmm: memory_manager: Make backing file from snapshot optional
Let's not assume that a backing file is going to be the result from
a snapshot for each memory region. These regions might be backed by
a file on the host filesystem (not a temporary file in host RAM), which
means they don't need to be copied and stored into dedicated files.

That's why this commit prepares for further changes by introducing an
optional PathBuf associated with the snapshot of each memory region.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-25 16:43:10 +02:00
Sebastien Boeuf
871138d5cc vm-migration: Make snapshot() mutable
There will be some cases where the implementation of the snapshot()
function from the Snapshottable trait will require to modify some
internal data, therefore we make this possible by updating the trait
definition with snapshot(&mut self).

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-25 16:43:10 +02:00
Sebastien Boeuf
7b898285d5 ci: Extend integration tests with user defined memory zones
Adding a small test to validate that user defined memory zones work as
expected when using --memory-zone option.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-25 16:43:10 +02:00
Sebastien Boeuf
c13721fdbd vmm: memory_manager: Handle user defined memory zones
In case the memory size is 0, this means the user defined memory
zones are used as a way to specify how to back the guest memory.

This is the first step in supporting complex use cases where the user
can define exactly which type of memory from the host should back the
memory from the guest.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-25 16:43:10 +02:00
Sebastien Boeuf
7cd3867e2c vmm: memory_manager: Provide file offset through create_ram_region()
In anticipation for the need to map part of a file with the function
create_ram_region(), it is extended to accept a file offset as argument.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-25 16:43:10 +02:00
Sebastien Boeuf
59d4a56ab7 vmm: memory_manager: Don't truncate backing file
In case the provided backing file is an actual file and not a directory,
we should not truncate it, as we expect the file to already be the right
size.

This change will be important once we try to map the same file through
multiple memory mappings. We can't let the file be truncated as the
second mapping wouldn't work properly.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-25 16:43:10 +02:00
Sebastien Boeuf
be475ddc22 main, vmm: Let the user define distincts memory zones
Introducing a new CLI option --memory-zone letting the user specify
custom memory zones. When this option is present, the --memory size
must be explicitly set to 0.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-25 16:43:10 +02:00
Sebastien Boeuf
d25ec66bb6 vmm: memory_manager: Simplify start_addr()
Small simplification for the function calculating the start address.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-25 16:43:10 +02:00
Anatol Belski
12212d2966 pci: device_manager: Remove hardcoded I/O port assignment
It is otherwise seems to be able to cause resource conflicts with
Windows APCI_HAL. The OS might do a better job on assigning resources
to this device, withouth them to be requested explicitly. 0xcf8 and
0xcfc are only what is certainly needed for the PCI device enumeration.

Signed-off-by: Anatol Belski <anatol.belski@microsoft.com>
2020-08-25 09:00:06 +02:00
Michael Zhao
a4222afd7c scripts: Remove the workaround for "with-serde" in unit tests on AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-08-24 10:59:08 +02:00
Michael Zhao
afc98a5ec9 vmm: Fix AArch64 clippy warnings of vmm and other crates
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-08-24 10:59:08 +02:00
Michael Zhao
46b8f38987 arch: Fix AArch64 clippy warnings of arch crate
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-08-24 10:59:08 +02:00
Michael Zhao
527e8e7b1d build: Add quality checks workflow for AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-08-24 10:59:08 +02:00
Amey Narkhede
dc9c12518e docs/iommu: Update cpu and memory option parameters
Use of backing file is deprecated hence use the `hugepages` field.
Also use the `boot` field for specifying number of cpus

Signed-off-by: Amey Narkhede <ameynarkhede02@gmail.com>
2020-08-24 08:49:47 +02:00
dependabot-preview[bot]
0c33bf0044 build(deps): bump syn from 1.0.38 to 1.0.39
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.38 to 1.0.39.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.38...1.0.39)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-24 06:48:33 +00:00
Muminul Islam
92b4499c1e vmm, hypervisor: Add vmstate to snapshot and restore path
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-08-24 08:48:15 +02:00
Muminul Islam
77e901a602 hypervisor: Introduce VM state to Vm hypervisor trait
We may need to store hypervisor speciific data to the VM. This support is
needed for Microsoft hyperv implementations. This patch introduces two
new definitions to Vm trait and implements for KVM.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-08-24 08:48:15 +02:00
dependabot-preview[bot]
8962e25268 build(deps): bump miniz_oxide from 0.4.0 to 0.4.1
Bumps [miniz_oxide](https://github.com/Frommi/miniz_oxide) from 0.4.0 to 0.4.1.
- [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.4.0...0.4.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-24 04:00:04 +00:00
Wei Liu
47e8f5475e pci/msix: remove reference to KVM from a comment
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-08-21 16:23:41 +02:00
Wei Liu
e6849699d2 vfio: remove KVM-ism from comments and error messages
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-08-21 16:23:41 +02:00
Wei Liu
571c368528 vfio: fix comment for map_mmio_regions
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-08-21 16:23:41 +02:00
dependabot-preview[bot]
57ff608be9 build(deps): bump libc from 0.2.74 to 0.2.76
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.74 to 0.2.76.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.74...0.2.76)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-21 07:08:35 +00:00
dependabot-preview[bot]
da72d30f53 build(deps): bump ppv-lite86 from 0.2.8 to 0.2.9
Bumps [ppv-lite86](https://github.com/cryptocorrosion/cryptocorrosion) from 0.2.8 to 0.2.9.
- [Release notes](https://github.com/cryptocorrosion/cryptocorrosion/releases)
- [Commits](https://github.com/cryptocorrosion/cryptocorrosion/compare/ppv-lite86-0.2.8...ppv-lite86-0.2.9)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-21 06:17:47 +00:00
dependabot-preview[bot]
1c9c0fa0e5 build(deps): bump linux-loader from 726360b to 3cf96c5
Bumps [linux-loader](https://github.com/rust-vmm/linux-loader) from `726360b` to `3cf96c5`.
- [Release notes](https://github.com/rust-vmm/linux-loader/releases)
- [Commits](726360bb2c...3cf96c53ed)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-21 06:17:35 +00:00
dependabot-preview[bot]
421f1c9d8b build(deps): bump autocfg from 1.0.0 to 1.0.1
Bumps [autocfg](https://github.com/cuviper/autocfg) from 1.0.0 to 1.0.1.
- [Release notes](https://github.com/cuviper/autocfg/releases)
- [Commits](https://github.com/cuviper/autocfg/compare/1.0.0...1.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-21 04:14:36 +00:00
Sebastien Boeuf
d751f419de Jenkinsfile: Force the cleanup after stages are aborted
Problem with the previous solution was that Cleanup stage was not
executed when previous stages failed. We fix this by adding a post
section that executes always after the Aarch64 build completed, no
matter if it has failed, succeeded or been aborted.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-19 09:26:36 -07:00
Michael Zhao
cd0b8ed8f8 virtio-devices: Allowing SYS_write syscall for virtio-net-ctl thread
"debug!" marco is used in virtio-devices/src/epoll_helper.rs. When"-vvv"
and "--log-file" option was specified, the missing "SYS_write" rule
caused a "bad system call" crash.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-08-19 14:26:07 +02:00
Sebastien Boeuf
bcbc098c66 Jenkinsfile: Add a cleanup stage
Cleanup of the Aarch64 machine can't be done as part of the parallel
stage as this is often skipped. When the build is aborted because
another parallel stage failed, the post actions are simply not
performed. That's why we need a dedicated stage, out of the parallel
ones, to cleanup the Aarch64 machine.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-19 11:23:06 +02:00
Amey Narkhede
9304b92219 docs/virtio-fs: Update --memory option parameters
Use updated --memory option parameters. The field `size` needs
M/G suffix. Without the suffix cloud-hypervisor panics at
src/main.rs:353
Also the use of backing file is deprecated so use `shared` field

Signed-off-by: Amey Narkhede <ameynarkhede02@gmail.com>
2020-08-19 10:43:04 +02:00
Bo Chen
02d87833f0 virtio-devices: seccomp: Add seccomp filters for vhost_blk thread
This patch enables the seccomp filters for the vhost_blk worker thread.

Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-19 08:33:58 +02:00
Bo Chen
4e0ea15075 virtio-devices: seccomp: Add seccomp filter for vhost_net thread
This patch enables the seccomp filters for the vhost_net worker thread.

Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-19 08:33:58 +02:00
Bo Chen
896b9a1d4b virtio-devices: seccomp: Add seccomp filter for vhost_net_ctl thread
This patch enables the seccomp filters for the vhost_net_ctl worker thread.

Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-19 08:33:58 +02:00
Bo Chen
02d63149fe virtio-devices: seccomp: Add seccomp filters for vhost_fs thread
This patch enables the seccomp filters for the vhost_fs worker thread.

Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-19 08:33:58 +02:00
Bo Chen
c82ded8afa virtio-devices: seccomp: Add seccomp filters for balloon thread
This patch enables the seccomp filters for the balloon worker thread.

Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-19 08:33:58 +02:00
Bo Chen
c460178723 virtio-devices: seccomp: Add seccomp filters for mem thread
This patch enables the seccomp filters for the mem worker thread.

Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-19 08:33:58 +02:00
dependabot-preview[bot]
c30ff62a7a build(deps): bump libssh2-sys from 0.2.18 to 0.2.19
Bumps [libssh2-sys](https://github.com/alexcrichton/ssh2-rs) from 0.2.18 to 0.2.19.
- [Release notes](https://github.com/alexcrichton/ssh2-rs/releases)
- [Commits](https://github.com/alexcrichton/ssh2-rs/compare/libssh2-sys-0.2.18...libssh2-sys-0.2.19)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-19 06:24:42 +00:00
dependabot-preview[bot]
58d0aec510 build(deps): bump cc from 1.0.58 to 1.0.59
Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.58 to 1.0.59.
- [Release notes](https://github.com/alexcrichton/cc-rs/releases)
- [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.58...1.0.59)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-19 06:24:29 +00:00
Michael Zhao
24fb5c8387 tests: Enable test case test_counters on AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-08-18 08:10:04 +02:00
Bo Chen
de3b17d948 virtio-devices: Print out worker thread errors
As we never join the spawned virtio-devices worker threads, the error
returned from each worker thread is lost. For now, we simply print out
the error from each worker thread.

Fixes: #1551

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-18 07:57:11 +02:00
dependabot-preview[bot]
df30b23f0c build(deps): bump once_cell from 1.4.0 to 1.4.1
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.4.0 to 1.4.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.4.0...v1.4.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-18 05:55:55 +00:00
dependabot-preview[bot]
4cde183783 build(deps): bump tinyvec from 0.3.3 to 0.3.4
Bumps [tinyvec](https://github.com/Lokathor/tinyvec) from 0.3.3 to 0.3.4.
- [Release notes](https://github.com/Lokathor/tinyvec/releases)
- [Commits](https://github.com/Lokathor/tinyvec/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-18 05:55:43 +00:00
dependabot-preview[bot]
f02a5d0915 build(deps): bump libz-sys from 1.0.27 to 1.1.0
Bumps [libz-sys](https://github.com/rust-lang/libz-sys) from 1.0.27 to 1.1.0.
- [Release notes](https://github.com/rust-lang/libz-sys/releases)
- [Commits](https://github.com/rust-lang/libz-sys/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-18 05:55:31 +00:00
Bo Chen
aaa02a0d78 virtio-devices: seccomp: Add 'brk' syscall to all worker threads
To prevent potential failures, this patch adds 'brk' syscall to all
virtio-devices worker threads.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-17 21:08:49 +02:00
Bo Chen
c90a71e329 virtio-devices: seccomp: Add 'brk' syscall to the rng thread
From the experiments of running integration tests on my local machine,
auditd occationally reported the 'brk' syscall is needed for the
'virtio-rng' worker thread.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-17 21:08:49 +02:00
Bo Chen
c70ad27247 virtio-devices: Add seccomp filter list for net worker thread
This patch adds the seccomp filter list for the virtio_net thread, while
the list was already added for the virtio_net_ctl thread.

Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-17 21:08:49 +02:00
Bo Chen
3d6d9ca4de virtio-devices: Print out error message from the net worker thread
Partially fixes: #1551

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-17 21:08:49 +02:00
Bo Chen
1bf7817c40 virtio-devices: seccomp: Distinguish viritio-net-ctl from virtio-net
The current seccomp filter for virtio-net is actually for the worker
thread 'virtio_net_ctl' (not the actual worker thread
'virtio_net'). This patch introduces changes to distinguish those two
worker threads and seccomp filters.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-17 21:08:49 +02:00
Bo Chen
4539236690 virtio-devices: seccomp: Add seccomp filters for iommu thread
This patch enables the seccomp filters for the iommu worker thread.

Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-17 21:08:49 +02:00
Bo Chen
dc6c62af09 virtio-devices: Print out error message from the iommu worker thread
Partially fixes: #1551

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-17 21:08:49 +02:00
dependabot-preview[bot]
d71142277c build(deps): bump libz-sys from 1.0.25 to 1.0.27
Bumps [libz-sys](https://github.com/rust-lang/libz-sys) from 1.0.25 to 1.0.27.
- [Release notes](https://github.com/rust-lang/libz-sys/releases)
- [Commits](https://github.com/rust-lang/libz-sys/compare/1.0.25...1.0.27)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-17 07:14:15 +00:00
Sebastien Boeuf
17a0733527 Jenkinsfile: Don't retry integration tests on failure
We recently added the ability for the gnu and musl workers to retry if
integration test were not passing, relying on some simple Jenkins
options. Unfortunately, this is not working as expected as the retries
never pass either. The suspected reason is the machine itself, which
might be scheduled on some specific hardware, which makes our VMs more
error prone.

Bottom line, on a faulty machine, the tests will always fail, therefore
there is no added value in retrying on the same machine.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-14 16:44:35 +02:00
Anatol Belski
eba42c392f devices: acpi: Add UID to devices with common HID
Some OS might check for duplicates and bail out, if it can't create a
distinct mapping. According to ACPI 5.0 section 6.1.12, while _UID is
optional, it becomes required when there are multiple devices with the
same _HID.

Signed-off-by: Anatol Belski <ab@php.net>
2020-08-14 08:52:02 +02:00
dependabot-preview[bot]
ebe61de0d1 build(deps): bump clap from 2.33.2 to 2.33.3
Bumps [clap](https://github.com/clap-rs/clap) from 2.33.2 to 2.33.3.
- [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/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-14 06:18:55 +00:00
Rob Bradford
01b1412914 Jenkinsfile: Move OpenAPI validation to worker
Remove this work from the Jenkins master.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-13 16:53:16 +01:00
Rob Bradford
cf1a1ac6cf Jenkinsfile: Stop running "cargo" checks on master
These checks are now handled via GitHub actions.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-13 16:09:24 +02:00
Rob Bradford
bf4051665c build: Run cargo-audit from a GitHub action
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-13 16:09:24 +02:00
Rob Bradford
6b40f2dbc5 virtio-devices: vsock: Fix clippy error
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-13 16:09:24 +02:00
Rob Bradford
1a01f2d82a qcow: raw_file: Fix clippy warning
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-13 16:09:24 +02:00
Rob Bradford
a4b67c2226 build: Use GitHub actions for clippy/build/rustfmt tests
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-13 16:09:24 +02:00
Sebastien Boeuf
aa57762c4f virtio-devices: Acknowledge a device being paused
Using the Rust Barrier mechanism, this patch forces each virtio device
to acknowledge they've been correctly paused before going further.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-13 14:52:18 +02:00
Rob Bradford
fd48779a0d tests: Port test_initramfs to new methodology
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-13 13:03:22 +02:00
Rob Bradford
dd39aedde1 tests: Port test_memory_mergeable to new methodology
As a compromise we only print out the first child's output.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-13 13:03:22 +02:00
Rob Bradford
9dd4625fb4 tests: Port test_virtio_vsock to new methodology
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-13 13:03:22 +02:00
Rob Bradford
4983e5c322 tests: Port test_virtio_pmem to new methodology
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-13 13:03:22 +02:00
Rob Bradford
7b621bde4f Jenkinsfile: chown the workspace before cleaning up
If the build was aborted then the dev_cli.sh code that is responsible
for changing the file ownership will not get run. This results in the
failure to delete some of the files in the workspace.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-13 09:10:46 +01:00
dependabot-preview[bot]
b9fbcd469c build(deps): bump linux-loader from b13674a to 726360b
Bumps [linux-loader](https://github.com/rust-vmm/linux-loader) from `b13674a` to `726360b`.
- [Release notes](https://github.com/rust-vmm/linux-loader/releases)
- [Commits](b13674ab87...726360bb2c)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-12 16:29:45 +00:00
Sebastien Boeuf
fca46fd00e virtio-devices: net: Add dup syscall to seccomp filters
The seccomp filters specific to the virtio-net threads must contain
dup() syscall now that we ported the epoll code to the EpollHelper.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-12 17:34:02 +02:00
Sebastien Boeuf
a502cb282e virtio-devices: net_ctrlq: Port to EpollHelper
Migrate virtio-net and vhost-user-net control queue to EpollHelper so
as to remove code duplication.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-12 17:34:02 +02:00
Rob Bradford
32b70e354c tests: Port virtiofs tests to new methodology
This required a bit of rearranging as it is not possible to call
prepare_daemon() inside a catch_unwind{} block.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-12 14:53:02 +01:00
Rob Bradford
23174800ca tests: Port vhost_user_block tests to new methodology
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-12 14:53:02 +01:00
Rob Bradford
8f4e1382a9 tests: Port vhost_user_net tests to new methodology
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-12 14:53:02 +01:00
Rob Bradford
effff460d4 tests: Port test_cpu_topology to new test methodology
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-12 14:53:02 +01:00
Sebastien Boeuf
821cf3add9 virtio-devices: vhost-user: Port to EpollHelper
Migrate all vhost-user devices to EpollHelper so as to remove code that
is duplicated between multiple virtio devices.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-12 14:39:54 +02:00
Rob Bradford
d749aa2e6b tests: Port test_vfio to new test methodology
Now the testing aspects are run inside a panic handler block rather than
inside a credibility TestBlock. If the test fails then the output from
the cloud-hypervisor binary is then presented.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-12 12:19:34 +02:00
Rob Bradford
4ef702ea76 tests: Use a disk image for test_vfio rather than virtio-fs
This reduces the complexity of the test slightly. The PCI BDFs in the L1
needed changing as the block devices come before the network ones.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-12 12:19:34 +02:00
Sebastien Boeuf
8fbc4b4004 virtio-devices: vsock: Port to EpollHelper
Migrate to EpollHelper so as to remove code that is duplicated between
multiple virtio devices.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-12 10:07:57 +01:00
Sebastien Boeuf
01e7bd7276 virtio-devices: Make EpollHandler more generic
Instead of passing only the event type through the handle_event()
callback, we make the trait slightly more generic by providing the
epoll event to each virtio device implementation.

This is particularly useful for vsock as it will need the event set.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-12 10:07:57 +01:00
dependabot-preview[bot]
1e0b516a84 build(deps): bump linux-loader from b309c9d to b13674a
Bumps [linux-loader](https://github.com/rust-vmm/linux-loader) from `b309c9d` to `b13674a`.
- [Release notes](https://github.com/rust-vmm/linux-loader/releases)
- [Commits](b309c9df17...b13674ab87)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-12 07:52:10 +00:00
dependabot-preview[bot]
31031b43b6 build(deps): bump smallvec from 1.4.1 to 1.4.2
Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.4.1 to 1.4.2.
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/compare/v1.4.1...v1.4.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-12 06:41:42 +00:00
Sebastien Boeuf
e7ed037351 virtio-devices: balloon: Port to EpollHelper
Migrate to EpollHelper so as to remove code that is duplicated between
multiple virtio devices.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-11 19:58:10 +01:00
Alyssa Ross
17ad86afe3 docs: use shared memory with vhost-user
Not doing this is an error.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2020-08-11 19:37:31 +02:00
Sebastien Boeuf
e8f0bdb6f2 virtio-devices: console: Add dup syscall to seccomp filters
The seccomp filters specific to the virtio-console thread must contain
dup syscall now that we ported the epoll code to the EpollHelper.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-11 19:17:50 +02:00
Sebastien Boeuf
d9992b5b5f virtio-devices: console: Port to EpollHelper
Migrate to EpollHelper so as to remove code that is duplicated between
multiple virtio devices.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-11 19:17:50 +02:00
Sebastien Boeuf
bdef54ead6 vmm: Add brk syscall to the API thread
The brk syscall is not always called as the system might not need it.
But when it's needed from the API thread, this causes the thread to
terminate as it is not part of the authorized list of syscalls.

This should fix some sporadic failures on the CI with the musl build.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-11 15:04:21 +01:00
Alyssa Ross
cb96afaa2f vhost_user_net: don't claim to impl all features
Even if the vhost-user-net device did implement all currently-defined
features, it would be very short-sighted to use ::all(), because if a
new feature was defined later, the device would start claiming to
implement it even though it didn't.

More practically, claiming to implement all features breaks using QEMU
with the cloud-hypervisor vhost-user-net backend, because QEMU will
negotiate VHOST_USER_PROTOCOL_F_SLAVE_REQ, and then break when the
communication channel isn't actually set up.

I wasn't sure exactly which features the backend should claim to
implement, though.  Definitely MQ, and I'm fairly certain none of the
features I've ommitted are implemented.  But I'm not sure about
REPLY_ACK.  As far as I can tell it should be implemented entirely by
the vhost crate, with no cooperation required from the vhost-user-net
backend itself, so there should be no reason to let a frontend use it
if it wants to.  But despite this, neither vhost-user-fs nor
vhost-user-blk claims to implement it.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2020-08-11 12:58:26 +02:00
Rob Bradford
070f47246c tests: Port test_snapshot_restore to new methodology
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-11 12:57:18 +02:00
Rob Bradford
6cd31e7a4d tests: Introduce new test methodology
Rather than using a credible TestBlock to capture the test assertions
instead use a catch_unwind block to catch the panic and turn
it into a Result<>.

If block panicked or the child binary had non-zero exit then, and only
then, print out the child output.

This results in a clearer test output with no interleaving.

Currently only test_counters is ported to this methodology to
demonstrate its use.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-11 12:57:18 +02:00
Rob Bradford
5da55f0f2e tests: Remove "--nocapture" from tests
`cargo test` runs every test in its own process and by default will
collect the output from the test and only print it if the test fails.
`--nocapture` instead prints any output from the test immediately and
does not collate it - this leads to interleaving.

`--nocapture` might be useful for local test debugging but is not
something that is helpful, and is instead unhelpful for our CI as a
whole.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-11 12:57:18 +02:00
dependabot-preview[bot]
bfacf50d90 build(deps): bump serde_derive from 1.0.114 to 1.0.115
Bumps [serde_derive](https://github.com/serde-rs/serde) from 1.0.114 to 1.0.115.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.114...v1.0.115)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-11 05:47:30 +00:00
dependabot-preview[bot]
6812a63fca build(deps): bump serde from 1.0.114 to 1.0.115
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.114 to 1.0.115.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.114...v1.0.115)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-11 05:14:51 +00:00
Rob Bradford
c5a03d5ad4 build: Remove job directory on ARM64 build
This prevents the builder from running out of disk space.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-10 14:55:50 +01:00
Sebastien Boeuf
05c6136790 io-uring: Move to the crates.io 0.4.0 version
Now that io-uring crate has been stabilized, let's move to the latest
release 0.4.0 from crates.io.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-10 08:40:51 +01:00
Rob Bradford
66efe3cf53 virtio-devices: mem: Port to EpollHelper
Migrate to EpollHelper so as to remove code that is duplicated between
multiple virtio devices.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-10 08:46:35 +02:00
Anatol Belski
d4754e18f9 Cargo.toml: add missing [package] entries
These are required by some tools, but also by crates.io one day.

Signed-off-by: Anatol Belski <ab@php.net>
2020-08-10 08:44:09 +02:00
dependabot-preview[bot]
3bbed83e8e build(deps): bump io-uring from c00d968 to 445fbc4
Bumps [io-uring](https://github.com/tokio-rs/io-uring) from `c00d968` to `445fbc4`.
- [Release notes](https://github.com/tokio-rs/io-uring/releases)
- [Commits](c00d968b03...445fbc4ae4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-09 17:01:24 +00:00
Rob Bradford
1c4e8ac5ce Revert "build: Temporarily disable ARM64 builds"
This reverts commit 743ebe2fa6.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-07 10:35:50 +01:00
Rob Bradford
d714cf8131 build, release-notes.md: Document 0.9.0 release
Update release notes and version number for the new release.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-06 14:31:36 +01:00
Rob Bradford
8286b316c1 build: Bump vm-memory dependency
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-06 14:26:47 +01:00
Muminul Islam
96caf6b03b rpm: Add spec file for packaging cloud-hypervisor
Packaging the cloud-hyperviosr binary is useful for enterprise use.
This patch adds the spec file for x86_64. Aarch64 support is not added
yet.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-08-06 09:29:36 +01:00
Sebastien Boeuf
20cd778c5b ci: Retry integration tests if failing
Both gnu and musl workers will retry integration tests up to 3 times if
they fail. This should give us a better pass rate, without having to
restart the entire build every time a single glitch happens.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-06 08:29:50 +01:00
dependabot-preview[bot]
7529a9ac05 build(deps): bump seccomp from v0.21.2 to v0.22.0
Bumps [seccomp](https://github.com/firecracker-microvm/firecracker) from v0.21.2 to v0.22.0.
- [Release notes](https://github.com/firecracker-microvm/firecracker/releases)
- [Changelog](cc5387637c/CHANGELOG.md)
- [Commits](a06d358b2e...cc5387637c)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-06 07:25:30 +00:00
Bo Chen
f65372ea4a dev_cli: Remove the use of undefined '$libc' for the 'shell' command
Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-06 08:30:40 +02:00
dependabot-preview[bot]
8e8ec74b2a build(deps): bump clap from 2.33.1 to 2.33.2
Bumps [clap](https://github.com/clap-rs/clap) from 2.33.1 to 2.33.2.
- [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/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-05 20:36:12 +00:00
dependabot-preview[bot]
1ac6ccb300 build(deps): bump signal-hook-registry from 1.2.0 to 1.2.1
Bumps [signal-hook-registry](https://github.com/vorner/signal-hook) from 1.2.0 to 1.2.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/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-05 20:35:55 +00:00
Jose Carlos Venegas Munoz
90acb01bad vmm: seccomp: add mprotect to API thread filter
Add mprotect to API thread rules. Prevent the VMM is
killed when it is used.

Signed-off-by: Jose Carlos Venegas Munoz <jose.carlos.venegas.munoz@intel.com>
2020-08-05 21:35:21 +01:00
Rob Bradford
743ebe2fa6 build: Temporarily disable ARM64 builds
The builder is not currently responding to pings.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-05 17:51:20 +01:00
Anatol Belski
4f33ea89cf pci: use vfio-bindings from crates.io
This fixes `cargo vendor` throwing an error

```
$ cargo vendor
error: failed to sync

Caused by:
  found duplicate version of package `vfio-bindings v0.2.0` vendored from two sources:

	source 1: https://github.com/rust-vmm/vfio-bindings#f08cbcbf
	source 2: registry `https://github.com/rust-lang/crates.io-index`
```

Both sources are indeed same, the conflict is only cause by the
different URLs.

Signed-off-by: Anatol Belski <ab@php.net>
2020-08-05 17:50:45 +01:00
Sebastien Boeuf
0f1ab38ded hypervisor: kvm: Make MSRs set/get more flexible
Based on the way KVM_GET_MSRS and KVM_SET_MSRS work, both function are
very unlikely to fail, as they simply stop looping through the list of
MSRs as soon as getting or setting one fails. This is causing some
issues with the snapshot/restore feature, as on some platforms, we only
save a subset of the list of MSRs, leading to unproper way of saving the
VM.

The way to address this issue is by checking the number of MSRs get/set
matches the expected amount from the list. In case it does not match, we
simply ignore the failing MSR and continue getting/setting the rest of
the list. By doing this by iterations, we end up getting/setting as many
MSRs as the platform can support.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-05 14:52:35 +01:00
Rob Bradford
44cf97e2fd build: Fix Jenkinsfile syntax
Turns out that "when" blocks are permitted but not effectual in "post"
sections so instead use a script behaviour to make the message
conditional on build change.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-05 14:49:33 +01:00
Rob Bradford
b5d64be479 virtio-devices: iommu: Port to EpollHelper
Migrate to EpollHelper so as to remove code that is duplicated between
multiple virtio devices.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-05 13:15:23 +02:00
Rob Bradford
2e98208af5 build: Alert on Slack when master build regresses or is fixed
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-05 13:14:20 +02:00
Rob Bradford
55c16fecbf virtio-devices: seccomp: Add missing dup() syscalls
The refactoring to use EpollHelper added a requirement on this system
call.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-05 11:32:31 +02:00
Rob Bradford
0e335a709d virtio-devices: Print out worker error messages
Currently any messages generated during the worker thread are not
shown anywhere as the thread is never join()ed on. Instead output the
error immediately.

For now only cover the subset where the work to port to EpollHandler
clashed with the seccomp filtering for virtio devices.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-05 11:32:31 +02:00
dependabot-preview[bot]
ec9de259ba build(deps): bump seccomp from v0.21.1 to v0.21.2
Bumps [seccomp](https://github.com/firecracker-microvm/firecracker) from v0.21.1 to v0.21.2.
- [Release notes](https://github.com/firecracker-microvm/firecracker/releases)
- [Changelog](a06d358b2e/CHANGELOG.md)
- [Commits](047a379eb0...a06d358b2e)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-05 07:34:44 +00:00
Michael Zhao
fc2d9c6e31 ci: Remove unused image in sha1sums-aarch64
We no longer download focal-server-cloudimg-arm64.img, checking it
lead to a failure if "work_loads" folder is new.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-08-05 08:15:18 +01:00
Michael Zhao
f2db346127 tests: Enable more integration test cases on AArch64
Enabled 3 test cases:
- test_large_vm
- test_huge_memory
- test_serial_null

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-08-05 08:15:18 +01:00
Bo Chen
dc71d2765a virtio-devices: seccomp: Add seccomp filters for pmem thread
This patch enables the seccomp filters for the pmem worker thread.

Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-05 08:13:31 +01:00
Bo Chen
d77977536d virtio-devices: seccomp: Add seccomp filters for net thread
This patch enables the seccomp filters for the net worker thread.

Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-05 08:13:31 +01:00
Bo Chen
276df6b71c virtio-devices: seccomp: Add seccomp filters for console thread
This patch enables the seccomp filters for the console worker thread.

Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-05 08:13:31 +01:00
Bo Chen
a426221167 virtio-devices: seccomp: Add seccomp filters for rng thread
This patch enables the seccomp filters for the rng worker thread.

Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-05 08:13:31 +01:00
Bo Chen
6a26789222 virtio-devices: seccomp: Fix typos in the block module
Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-05 08:13:31 +01:00
dependabot-preview[bot]
3eeee63189 build(deps): bump syn from 1.0.37 to 1.0.38
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.37 to 1.0.38.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.37...1.0.38)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-05 06:43:20 +00:00
Rob Bradford
ce65093f8d virtio-devices: pmem: Port to EpollHelper
Migrate to EpollHelper so as to remove code that is duplicated between
multiple virtio devices.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-05 08:43:01 +02:00
Rob Bradford
e093f0e83e virtio-devices: rng: Port to EpollHelper
Migrate to EpollHelper so as to remove code that is duplicated between
multiple virtio devices.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-05 08:42:06 +02:00
Ricardo Koller
358b3c0b89 Dummy change to start the tests
Signed-off-by: Ricardo Koller <ricarkol@gmail.com>
2020-08-05 08:38:58 +02:00
Ricardo Koller
7589f1b3bf vhost_user_fs: increase RLIMIT_NOFILE
Increase the number of open files limit for the sandboxed process to the
maximum allowed in the system. The maximum is obtained by reading the
/proc/sys/fs/nr_open sysctl file, and the setting is done using the setrlimit
syscall. Failure to read or parse the nr_open file, or to set the rlimit
results in a panic.

Signed-off-by: Ricardo Koller <ricarkol@gmail.com>
2020-08-05 08:38:58 +02:00
Rob Bradford
8f39b5ef84 build: Update Cargo.lock for kvm-bindings
Point to the non-merge commit.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-08-04 16:50:06 +01:00
Henry Wang
a47da51539 ci: AArch64: Enable basic virtio_vsock test case for AArch64
This commit enables the test case for testing the basic function
of virtio_vsock (i.e. without the hotplug).

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-08-04 13:16:14 +01:00
Bo Chen
704edd544c virtio-devices: seccomp: Add seccomp_filter module
This patch added the seccomp_filter module to the virtio-devices crate
by taking reference code from the vmm crate. This patch also adds
allowed-list for the virtio-block worker thread.

Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-04 11:40:49 +02:00
Bo Chen
ff7ed8f628 vmm: Propagate the SeccompAction value to the Vm struct constructor
This patch propagates the SeccompAction value from main to the
Vm struct constructor (i.e. Vm::new_from_memory_manager), so that we can
use it to construct the DeviceManager and CpuManager struct for
controlling the behavior of the seccomp filters for vcpu/virtio-device
worker threads.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-04 11:40:49 +02:00
Bo Chen
8e74637ebb main, vmm: seccomp: Add the '--seccomp log' option
This patch extends the CLI option '--seccomp' to accept the 'log'
parameter in addition 'true/false'. It also refactors the
vmm::seccomp_filters module to support both "SeccompAction::Trap" and
"SeccompAction::Log".

Fixes: #1180

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-04 11:40:49 +02:00
Bo Chen
b41884a406 main, vmm: seccomp: Use SeccompAction instead of SeccompLevel
This patch replaces the usage of 'SeccompLevel' with 'SeccompAction',
which is the first step to support the 'log' action over system
calls that are not on the allowed list of seccomp filters.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-08-04 11:40:49 +02:00
dependabot-preview[bot]
bfc37bc8d3 build(deps): bump syn from 1.0.36 to 1.0.37
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.36 to 1.0.37.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.36...1.0.37)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-04 06:44:59 +00:00
Henry Wang
61c093f724 ci: AArch64: Enable api_create_boot for AArch64
This commit enables the `api_create_boot` case in the integration
test as the test for the Cloud Hypervisor API server functionality.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-08-03 14:15:14 +01:00
Sebastien Boeuf
8f0bf82648 io_uring: Add new feature gate
By adding a new io_uring feature gate, we let the user the possibility
to choose if he wants to enable the io_uring improvements or not.
Since the io_uring feature depends on the availability on recent host
kernels, it's better if we leave it off for now.

As soon as our CI will have support for a kernel 5.6 with all the
features needed from io_uring, we'll enable this feature gate
permanently.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-03 14:15:01 +01:00
Sebastien Boeuf
a85304196e virtio-devices: Improve error handling for virtio-blk io_uring
Instead of just logging error messages but continue the processing of
the queues, this patch returns errors right away. This allows for a
quicker detection of an error happening on the virtqueue.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-03 14:15:01 +01:00
Sebastien Boeuf
917027c55b vmm: Rely on virtio-blk io_uring when possible
In case the host supports io_uring and the specific io_uring options
needed, the VMM will choose the asynchronous version of virtio-blk.
This will enable better I/O performances compared to the default
synchronous version.

This is also important to note the VMM won't be able to use the
asynchronous version if the backend image is in QCOW format.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-03 14:15:01 +01:00
Sebastien Boeuf
64283726e7 virtio-devices: Add an asynchronous virtio-blk device
This introduces a new version of virtio-blk device. The default
virtio-blk provides synchronous processing of the queues, while this
new version relies on io_uring from the host kernel to provide an
asynchronous processing of the queues.

This new asynchronous version provides a huge performance improvement
compared to the default synchronous version.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-03 14:15:01 +01:00
Sebastien Boeuf
49a6500185 block_util: Add utilities to support io_uring
Creates a dedicated function relying on io_uring crate to execute
io_uring specific requests.

Also creates a function for checking io_uring support on the host.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-08-03 14:15:01 +01:00
Henry Wang
5807a91f33 scripts: AArch64: Fix abnormal integration script behaviour
PR#1511 introduced a `flock` command in order to let AArch64 CI
can be executed with multiple executors. However the command
```
(
    echo "try to lock $WORKLOADS_DIR folder and update"
    flock -x 12 && update_workloads
)
```
will introduce an abnormal behavior: If any error happened in
function `updated_workloads`, the sub-shell opened by the pair of
parentheses will be killed instead of the main shell, which is not
right.

This commit fixes this abnormal execution behaviour.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-07-31 14:08:15 +02:00
Henry Wang
d5863caa4d ci: AArch64: Enable virtio-fs integration test
This commit enables the virtio-fs related integration test cases
for AArch64.

Note that to run virtio-fs cases, the host kernel should be
newer than v5.5.

Fixes: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/1516

Signed-off-by: Henry Wang <henry.wang@arm.com>
2020-07-31 14:06:55 +02:00
Henry Wang
77ba041362 ci: AArch64: Update custom linux kernel to v5.8-rc4
This commit updates the AArch64 kernel config file and integration
test script to v5.8-rc4, and this update keeps the aarch64 guest
kernel in sync with the x86_64 one.

Fixes: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/1516

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-07-31 14:06:55 +02:00
Michael Zhao
44eccbe1af scripts: Remove the workaround for "with-serde" build error on AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-31 12:35:17 +01:00
Praveen Paladugu
afa8ecc90c vmm: add validation for network parameters
Signed-off-by: Praveen Paladugu <prapal@microsoft.com>
2020-07-31 09:07:12 +02:00
Wei Liu
a52b614a61 vmm: device_manager: console input should be only consumed by one device
Cloud Hypervisor allows either the serial or virtio console to output to
TTY, but TTY input is pushed to both.

This is not correct. When Linux guest is configured to spawn TTYs on
both ttyS0 and hvc0, the user effectively issues the same commands twice
in different TTYs.

Fix this by only direct input to the one choice that is using host side
TTY.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-30 18:05:01 +02:00
Wei Liu
5ed794a44c vmm: device_manager: rename console_input to virtio_console_input
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-30 18:05:01 +02:00
Michael Zhao
fec54f71b0 tests: Enable PCI integration test cases on AArch64
Enabled a minimum set of PCI test case.
More cases are to be adapted or debugged.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-30 09:52:12 +02:00
Michael Zhao
8e520d2415 resource: Enable PCI controller driver in AArch64 kernel config
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-30 09:52:12 +02:00
Wei Liu
3e68867bb7 vmm: device_manager: eliminate KvmMsiInterruptManager from the new function
The logic to create an MSI interrupt manager is applicable to Hyper-V as
well.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-30 08:00:33 +02:00
Michael Zhao
cf1b5156f4 scripts: Change AArch64 container network type BRIDGE
Changed the container network type to BRIDGE to seprate the networking
of parallel containers.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-29 18:32:44 +01:00
Michael Zhao
7e3cbf04de scripts: Improve AArch64 CI for parallel executors
Lock "work_loads" folder when one job is syncing files. If another job
arrives, wait until the lock is released.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-29 18:32:44 +01:00
dependabot-preview[bot]
12c5b7668a build(deps): bump libc from 0.2.73 to 0.2.74
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.73 to 0.2.74.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.73...0.2.74)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-28 20:46:37 +00:00
Muminul Islam
d49059a31b README: Fix copy command when using config from Cloud-hypervisor
The command which is mentioned in the README is wrong. We have two
cofigs one for x86_64 and another for aarh64. Previously it was a single
config. After adding the configs the read me was not modified. This
patch fixes the issue.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-07-28 21:09:22 +01:00
Wei Liu
218ec563fc vmm: fix warnings when KVM is not enabled
Some imports are only used by KVM. Some variables and code become dead
or unused when KVM is not enabled.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-28 21:08:39 +01:00
Howard Zhang
15bf61c6aa doc: AArch64: align rootfs name in arm64.md
Signed-off-by: Howard Zhang <howard.zhang@arm.com>
2020-07-28 10:38:13 +08:00
dependabot-preview[bot]
58f1051278 build(deps): bump pin-project from 0.4.22 to 0.4.23
Bumps [pin-project](https://github.com/taiki-e/pin-project) from 0.4.22 to 0.4.23.
- [Release notes](https://github.com/taiki-e/pin-project/releases)
- [Changelog](https://github.com/taiki-e/pin-project/blob/master/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project/compare/v0.4.22...v0.4.23)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-27 14:22:17 +00:00
dependabot-preview[bot]
35578f766a build(deps): bump proc-macro-hack from 0.5.16 to 0.5.18
Bumps [proc-macro-hack](https://github.com/dtolnay/proc-macro-hack) from 0.5.16 to 0.5.18.
- [Release notes](https://github.com/dtolnay/proc-macro-hack/releases)
- [Commits](https://github.com/dtolnay/proc-macro-hack/compare/0.5.16...0.5.18)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-27 13:08:25 +00:00
Sebastien Boeuf
8ad0e4d715 ci: Move to latest virtiofsd version
In order to follow the virtio-fs development, we rely on the latest
development branch regarding the virtio-fs daemon. It will be now build
from virtio-fs-dev branch from the virtio-fs maintainers repository.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-27 14:03:05 +01:00
Sebastien Boeuf
8dc0f49ba5 deps: Update vhost dependency
Move to latest vhost version, as it contains the updated list of
vhost-user protocol features along with the updated list of virtio-fs
slave commands.

This will allow Cloud-Hypervisor to work with latest virtiofsd binary.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-27 14:03:05 +01:00
dependabot-preview[bot]
6bf0d381e1 build(deps): bump serde_json from 1.0.56 to 1.0.57
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.56 to 1.0.57.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.56...v1.0.57)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-27 12:12:14 +00:00
Jianyong Wu
d24b110519 seccomp: AArch64: Add SYS_unlinkat to seccomp whitelist
This commit fixes an "Bad syscall" error when shutting down the VM
on AArch64 by adding the SYS_unlinkat syscall to the seccomp
whitelist.

Signed-off-by: Jianyong Wu <jianyong.wu@arm.com>
2020-07-27 07:25:07 +00:00
dependabot-preview[bot]
948cd20bfa build(deps): bump syn from 1.0.35 to 1.0.36
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.35 to 1.0.36.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.35...1.0.36)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-27 06:21:51 +00:00
dependabot-preview[bot]
9eb6d45c40 build(deps): bump anyhow from 1.0.31 to 1.0.32
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.31 to 1.0.32.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.31...1.0.32)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-25 08:59:42 +00:00
Rob Bradford
56bfe2700d virtio-devices, net_util: Migrate virtio-net to EpollHelper
EpollHelper allows the removal of much duplicated loop handling code and
instead the device specific even handling is delegated via an
implementation of EpollHelperHandler.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-24 13:50:37 +02:00
Rob Bradford
d66fa942be virtio-devices: Implement AsRawFd for EpollHelper
This is required for implementing virtio-net as the epoll RawFd must be
assigned into the NetQueuePair.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-24 13:50:37 +02:00
Rob Bradford
1dcf1b11e4 virtio-devices: Reserve first 16 events for the EpollHelper
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-24 13:50:37 +02:00
dependabot-preview[bot]
609f34fa43 build(deps): bump micro_http from c9ffb90 to 40309b7
Bumps [micro_http](https://github.com/firecracker-microvm/micro-http) from `c9ffb90` to `40309b7`.
- [Release notes](https://github.com/firecracker-microvm/micro-http/releases)
- [Commits](c9ffb90aeb...40309b72ee)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-24 06:42:53 +00:00
Rob Bradford
9ae44aeada vmm: acpi_tables: Fix PM timer I/O port width
Ensure that the width of the I/O port is correctly set to 32-bits in the
generic address used for the X_PM_TMR_BLK. Do this by type
parameterising GenericAddress::io_port_address() fuction.

TEST=Boot with clocksource=acpi_pm and observe no errors in the dmesg.

Fixes: #1496

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-23 17:48:22 +02:00
Rob Bradford
5cad2334dd virtio-block: Port to EpollHelper
Port virtio-block device to the new EpollHelper. This required moving
the queue EventFd ownership to BlockEpollHandler.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-23 13:10:34 +01:00
Rob Bradford
7d9dc4013e virtio-devices: Introduce EpollHelper
This is a helper for implementing the worker thread for virtio devices
and in particular handles special behaviour for pause and kill events.

The device specific event handling (for the queues themselves) is
delegated to a method invoked on a new EpollHelperHandler trait. This
method is passed the event as well as the EpollHelper so that it can
operate on the handler in order to manage events itself (required for
virtio-net.)

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-23 13:10:34 +01:00
Rob Bradford
aae5d988e1 devices: vmm: Add ACPI PM timer
This is a counter exposed via an I/O port that runs at 3.579545MHz. Here
we use a hardcoded I/O and expose the details through the FADT table.

TEST=Boot Linux kernel and see the following in dmesg:

[    0.506198] clocksource: acpi_pm: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 2085701024 ns

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-23 13:10:21 +01:00
Sebastien Boeuf
4fc7eb3daa docs: Add snapshot/restore documentation
Add some documentation regarding the snapshot/restore feature which was
introduced earlier, explaining how the feature works and how to use it
properly.

Fixes #1490

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-22 12:49:34 +01:00
Rob Bradford
08288305ef devices: cmos: Populate Update in Progress bit (UIP)
This bit should be set for the last 224us of each second. To be able to
fill this bit we need to use clock_gettime() to get the nanoseconds.
Also set the frequency bit to indicate we update at 32kHz.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-22 09:57:46 +02:00
Wei Liu
f03afea0d6 device_manager: document unsafe block in add_vfio_device
It is not immediately obvious why the conversion is safe. Document the
safety guarantee.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-21 17:13:10 +01:00
Samuel Ortiz
be51ea250d device_manager: Simplify the passthrough internal API
We store the device passthrough handler, so we should use it through our
internal API and only carry the passed through device configuration.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-07-21 17:20:25 +02:00
Michael Zhao
f57d970451 arch: Code cleanup after refactoring aarch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-21 16:22:02 +02:00
Michael Zhao
ddf1b76906 hypervisor: Refactor create_passthrough_device() for generic type
Changed the return type of create_passthrough_device() to generic type
hypervisor::Device.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-21 16:22:02 +02:00
Michael Zhao
6c8749adf2 arch: Switch to hypervisor crate
Removed the dependency on kvm-bindings and kvm-ioctls, use hypervisor
crate instead.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-21 16:22:02 +02:00
Michael Zhao
e7288888cf hypervisor: Extend hypervisor crate with Device trait
Added Device trait and KvmDevice struct for KVM-emulated devices.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-21 16:22:02 +02:00
Michael Zhao
e3e771727a arch: Refactor GIC code to seperate KVM specific code
Shrink GICDevice trait to contain hypervisor agnostic API's only, which
are used in generating FDT.
Move all KVM specific logic into KvmGICDevice trait.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-21 16:22:02 +02:00
Rob Bradford
6e8c8991d9 fuzz: qcow: Remove unnecessary "use libc"
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-20 20:22:47 +02:00
Rob Bradford
191f64028a fuzz: Add a fuzzer for virtio-devices::Block
This is based on the block fuzzer from crosvm and ported to Cloud
Hypervisor.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-20 20:22:47 +02:00
dependabot-preview[bot]
d922986d78 build(deps): bump syn from 1.0.34 to 1.0.35
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.34 to 1.0.35.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.34...1.0.35)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-20 17:38:11 +00:00
Michael Zhao
b363d1c706 tests: Enable integration test for initramfs on AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-20 14:20:53 +01:00
Michael Zhao
3e051e7b2c arch, vmm: Enable initramfs on AArch64
Ported Firecracker commit 144b6c.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-20 14:20:53 +01:00
Henry Wang
f449aec78e ci: AArch64: Enable AArch64 mmio-related integration test cases
This commit enables some mmio-related integration test cases on
AArch64, including:
* some vhost_user test cases
* virtio-blk test cases
* pmem test cases

Also this commit contains a bug fix in creating virtio-blk device.
Previously, when creating the FDT, the virtio-blk device was
labeled in the reverse order of address allocation.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-07-20 11:45:47 +01:00
dependabot-preview[bot]
07b6026f45 build(deps): bump proc-macro2 from 1.0.18 to 1.0.19
Bumps [proc-macro2](https://github.com/alexcrichton/proc-macro2) from 1.0.18 to 1.0.19.
- [Release notes](https://github.com/alexcrichton/proc-macro2/releases)
- [Commits](https://github.com/alexcrichton/proc-macro2/compare/1.0.18...1.0.19)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-20 08:06:29 +00:00
Sebastien Boeuf
840445096a docs: Add Intel SGX documentation
Adding a few notes and links about how to enable and use SGX through
Cloud-Hypervisor.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-20 09:06:06 +01:00
Wei Liu
e1af251c9f vmm, hypervisor: adjust set_gsi_routing / set_gsi_routes
Make set_gsi_routing take a list of IrqRoutingEntry. The construction of
hypervisor specific structure is left to set_gsi_routing.

Now set_gsi_routes, which is part of the interrupt module, is only
responsible for constructing a list of routing entries.

This further splits hypervisor specific code from hypervisor agnostic
code.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-20 07:32:32 +02:00
dependabot-preview[bot]
12b37ef13b build(deps): bump libc from 0.2.72 to 0.2.73
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.72 to 0.2.73.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.72...0.2.73)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-20 05:15:24 +00:00
Wei Liu
d484a3383c vmm: device_manager: introduce add_passthrough_device
It calls add_vfio_device on KVM or returns an error when not running on
KVM.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-17 20:21:39 +02:00
Wei Liu
821892419c vmm: device_manager: use generic names for passthrough device
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-17 20:21:39 +02:00
Wei Liu
ff8d7bfe83 hypervisor: add create_passthrough_device call to Vm trait
That function is going to return a handle for passthrough related
operations.

Move create_kvm_device code there.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-17 20:21:39 +02:00
Samuel Ortiz
7bfe87b7af README: Refer to the community repository
We now have a defined governance model.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-07-17 12:56:37 +02:00
Rob Bradford
4d878418e5 fuzz: Add fuzzing infrastructure and QCOW fuzzer
Add the basic infrastructure for fuzzing along with a qcow fuzzer ported
from crosvm and adapted to our code.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-17 08:49:35 +02:00
dependabot-preview[bot]
9267628e7c build(deps): bump vfio-ioctls from 195d6c6 to 49cc362
Bumps [vfio-ioctls](https://github.com/cloud-hypervisor/vfio-ioctls) from `195d6c6` to `49cc362`.
- [Release notes](https://github.com/cloud-hypervisor/vfio-ioctls/releases)
- [Commits](195d6c6eb0...49cc3626f6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-17 06:45:58 +00:00
Wei Liu
c08d2b2c70 device_manager: avoid manipulating MemoryRegion fields directly
Hyper-V may have different field names. Use make_user_memory_region
instead.

No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-16 15:56:03 +02:00
Rob Bradford
dfd6f3471d virtio-devices: vhost_user: block: Only change mutable field in write_config()
The only driver writable field in the virtio-block specification is the
writeback one. Check that the offset being written to is for that field
and update it.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-16 13:17:22 +02:00
Rob Bradford
eabcd618ba virtio-devices: block: Only change mutable field in write_config()
The only driver writable field in the virtio-block specification is the
writeback one. Check that the offset being written to is for that field
and update it.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-16 13:17:22 +02:00
Rob Bradford
751a302050 virtio-devices: Port devices over to new read_config_from_slice() helper
Using this helper removes lots of duplicated code across the devices.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-16 13:17:22 +02:00
Rob Bradford
d262540857 virtio-devices: Introduce helper for implementing read_config()
Add a helper function to share code between implementations that can use
a slice accessible data structure for configuration data.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-16 13:17:22 +02:00
Rob Bradford
5d67338b29 virtio-devices: Remove warning generating read_config() implementation
The version in VirtioDevice can be used instead.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-16 13:17:22 +02:00
Rob Bradford
676322c3cc virtio-devices: vsock: Remove write_config() implementation
This warning generating implementation can be handled by the version in
VirtioDevice.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-16 13:17:22 +02:00
Rob Bradford
580739f776 virtio-devices: vhost_user: fs: Remove write_config() implementation
All the configuration fields for virtio-fs are read only for the driver.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-16 13:17:22 +02:00
Rob Bradford
15d5cc62ff virtio-devices: vhost_user: net: Remove write_config implementation
The spec specifies that all fields are read-only from the driver.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-16 13:17:22 +02:00
Rob Bradford
f1e940df8d virtio-devices: net: Remove write_config implementation
The spec specifies that all fields are read-only from the driver.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-16 13:17:22 +02:00
Rob Bradford
e3dc620146 virtio-devices: Remove write_config implementations
Remove the write_config() implementations that only generate a warning
as that is now done at the VirtioDevice level.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-16 13:17:22 +02:00
Rob Bradford
6ba1c4318e virtio-devices: Add default implementations for {read,write}_config
Not every virtio device has any config fields that can be read and most
have none that can be written to.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-16 13:17:22 +02:00
Michael Zhao
f1419d116d docs: Update AArch64 doc to use KVM feature
Updated the build instructions to adapt to new added KVM feature.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-16 11:00:32 +02:00
Michael Zhao
2de4f73275 arch: Add log messages in GIC creation
The retry order to create virtual GIC is GICv3-ITS, GICv3 and GICv2.
But there was not log message to show what was finally created.
The log messages also mute the warning for unused "log" crate.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-16 11:00:32 +02:00
Bo Chen
48966b4535 docs: Update API documentation about '/vm.remove-device'
With recent changes (#1030 #1084), the '/vm.remove-device' API is no
longer restricted to remove VFIO PCI devices. It now supports (almost)
all hotpluggable devices, e.g. disk/net/pmem/fs/vsock.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2020-07-16 07:35:26 +02:00
Muminul Islam
053ea5dcd3 vfio: Make vfio to use MemoryRegion instead of kvm_userspace_memory_region
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-07-16 07:34:27 +02:00
dependabot-preview[bot]
cc57467d10 build(deps): bump log from 0.4.8 to 0.4.11
Bumps [log](https://github.com/rust-lang/log) from 0.4.8 to 0.4.11.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.8...0.4.11)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-16 05:33:44 +00:00
Wei Liu
d80e383dbb arch: move test cases to vmm crate
This saves us from adding a "kvm" feature to arch crate merely for the
purpose of running tests.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-15 17:21:07 +02:00
Wei Liu
598eaf9f86 vmm: use hypervisor::new in test_vm
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-15 17:21:07 +02:00
Wei Liu
11ffc83365 arch: use hypervsisor::new in test cases
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-15 17:21:07 +02:00
Wei Liu
085d165f8a bin: switch to hypervisor::new
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-15 17:21:07 +02:00
Wei Liu
a83bd97e0d hypervisor: introduce a new function
It returns an hypervisor object depending on which hypervisor is
configured.  Currently it only supports KVM.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-15 17:21:07 +02:00
Sebastien Boeuf
a5c4f0fc6f arch, vmm: Add e820 entry related to SGX EPC region
SGX expects the EPC region to be reported as "reserved" from the e820
table. This patch adds a new entry to the table if SGX is enabled.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-15 15:08:56 +02:00
Sebastien Boeuf
e10d9b13d4 arch, hypervisor, vmm: Patch CPUID subleaves to expose EPC sections
The support for SGX is exposed to the guest through CPUID 0x12. KVM
passes static subleaves 0 and 1 from the host to the guest, without
needing any modification from the VMM itself.

But SGX also relies on dynamic subleaves 2 through N, used for
describing each EPC section. This is not handled by KVM, which means
the VMM is in charge of setting each subleaf starting from index 2
up to index N, depending on the number of EPC sections.

These subleaves 2 through N are not listed as part of the supported
CPUID entries from KVM. But it's important to set them as long as index
0 and 1 are present and indicate that SGX is supported.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-15 15:08:56 +02:00
Sebastien Boeuf
1603786374 vmm: Pass MemoryManager through CpuManager creation
Instead of passing the GuestMemoryMmap directly to the CpuManager upon
its creation, it's better to pass a reference to the MemoryManager. This
way we will be able to know if SGX EPC region along with one or multiple
sections are present.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-15 15:08:56 +02:00
Sebastien Boeuf
2b06ce0ed4 vmm: Add EPC device to ACPI tables
The SGX EPC region must be exposed through the ACPI tables so that the
guest can detect its presence. The guest only get the full range from
ACPI, as the specific EPC sections are directly described through the
CPUID of each vCPU.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-15 15:08:56 +02:00
Sebastien Boeuf
84cf12d86a arch, vmm: Create SGX virtual EPC sections from MemoryManager
Based on the presence of one or multiple SGX EPC sections from the VM
configuration, the MemoryManager will allocate a contiguous block of
guest address space to hold the entire EPC region. Within this EPC
region, each EPC section is memory mapped.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-15 15:08:56 +02:00
Sebastien Boeuf
d9244e9f4c vmm: Add option for enabling SGX EPC regions
Introducing the new CLI option --sgx-epc along with the OpenAPI
structure SgxEpcConfig, so that a user can now enable one or multiple
SGX Enclave Page Cache sections within a contiguous region from the
guest address space.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-15 15:08:56 +02:00
Rob Bradford
1842865823 build: Add missing "hypervisor" crate from workspace
Also rearrange the workspace members so they are in alphabetical order.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-15 13:09:21 +02:00
Rob Bradford
9c867edc35 vhost_user_block, virtio-devices, block_util: Extract common block code
Extract the code that is used by vhost_user_block from the
virtio-devices crate to remove the dependencies on unrequired
functionality such as the virtio transports.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-15 10:17:11 +01:00
dependabot-preview[bot]
ce79482ec4 build(deps): bump linux-loader from ec930d7 to b309c9d
Bumps [linux-loader](https://github.com/rust-vmm/linux-loader) from `ec930d7` to `b309c9d`.
- [Release notes](https://github.com/rust-vmm/linux-loader/releases)
- [Commits](ec930d700f...b309c9df17)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-15 07:03:06 +00:00
Henry Wang
5a2ff98917 ci: AArch64: Add a build stage for musl toolchain
This commit adds required environment configurations to the
`dev_cli.sh` and a Jenkins stage to enable AArch64 binary
building using musl toolchain.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-07-15 08:19:15 +02:00
Henry Wang
e81402e76e ci: AArch64: Refactor custom linux kernel building strategy
As the current AArch64 integration test builds kernel every time,
which would take unnecessary time in CI and therefore not ideal.

This commit refactors the AArch64 kernel building strategy to:
1. Keep the Linux kernel source code directory instead of deleting
it everytime after the kernel is built.

2. In integration test script, check if the Linux kernel source
code directory exists. If so use `git fetch && git checkout -f` to
keep the source code always updated, else run `git clone` to get
the source code.

3. Copy config file in and then compile the kernel.

Fixes: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/1444

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-07-15 08:10:20 +02:00
Rob Bradford
dc55e45977 pci: Introduce and use PciBar struct
This simplies some of the handling for PCI BARs particularly with
respect to snapshot and restore. No attempt has been made to handle the
64-bit bar handling in a different manner to that which was used before.

Fixes: #1153

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-15 07:59:33 +02:00
Michael Zhao
cbb1f4cc2d docs: Add document for using PCI on AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-14 14:34:54 +01:00
Michael Zhao
cce6237536 pci: Enable GSI routing (MSI type) for AArch64
In this commit we saved the BDF of a PCI device and set it to "devid"
in GSI routing entry, because this field is mandatory for GICv3-ITS.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-14 14:34:54 +01:00
Michael Zhao
82a0e29c7a hypervisor: Export check_extension() API from hypervisor::Vm
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-14 14:34:54 +01:00
Michael Zhao
f2e484750a arch: aarch64: Add PCIe node in FDT for AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-14 14:34:54 +01:00
Michael Zhao
598bcf1459 arch: aarch64: Add GICv3-ITS on AArch64
GICv3-ITS is needed for MSI handling.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-14 14:34:54 +01:00
Michael Zhao
17057a0dd9 vmm: Fix build errors with "pci" feature on AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-14 14:34:54 +01:00
dependabot-preview[bot]
9ec4aa4019 build(deps): bump vfio-ioctls from 4c56812 to 195d6c6
Bumps [vfio-ioctls](https://github.com/cloud-hypervisor/vfio-ioctls) from `4c56812` to `195d6c6`.
- [Release notes](https://github.com/cloud-hypervisor/vfio-ioctls/releases)
- [Commits](4c568127fe...195d6c6eb0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-13 16:53:05 +00:00
Wei Liu
e5552a53d8 arch, pci: rename vm_fd to vm
The type is now hypervisor::Vm. Switch from KVM specific name vm_fd to a
generic name just like 8186a8eee6 ("vmm: interrupt: Rename vm_fd").

No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-13 16:08:00 +01:00
Sebastien Boeuf
8be80aca80 ci: Give some time to the disk hotplug
Under high load, the VM might take some time to hotplug the disk after
the hotplug command has been issued. For this reason, let's put a 10s
sleep before checking for the presence of the new disk.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-13 12:19:24 +02:00
Sebastien Boeuf
802f02532a ci: Extend test_vfio time before VM is ready
We want to give the time to the nested VM to be fully ready before we
check it's correctly setup. This involves 3 layers of virtualization
when running the CI on Azure, which added to the high load happening
because of the parallelization, adds up to the start up time.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-13 12:19:24 +02:00
Hui Zhu
165568e98b virtio-mem: Update VirtioMemConfig according to Linux kernel
Types of block_size and padding is updated in
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=544fc7dbbf920a3e64d109c416ee229e8e1763c5.
Update VirtioMemConfig according to it.

Signed-off-by: Hui Zhu <teawater@antfin.com>
2020-07-13 12:19:24 +02:00
Sebastien Boeuf
3cc8ca4ea5 virtio-devices: Update virtio-iommu to follow 5.8-rc4 kernel
The virtio configuration structures have been slightly modified between
5.6-rc4 and 5.8-rc4, forcing the virtio-iommu device to be updated
accordingly.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-13 12:19:24 +02:00
Sebastien Boeuf
2721a7004f ci: Update guest kernel to v5.8-rc4
Updating the kernel from 5.6-rc4 to 5.8-rc4 allows us to remove the
dependency on both virtio-vsock and virtio-mem patches as they are now
part of the upstream kernel. We're still carrying virtio-iommu and
virtio-fs patches.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-13 12:19:24 +02:00
Rob Bradford
81ce8f505c tests: Enable virtio-mmio tests for virtio-console
This is useful to ensure that virtio-console support is covered.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-13 10:16:03 +02:00
dependabot-preview[bot]
3800acd347 build(deps): bump adler from 0.2.2 to 0.2.3
Bumps [adler](https://github.com/jonas-schievink/adler) from 0.2.2 to 0.2.3.
- [Release notes](https://github.com/jonas-schievink/adler/releases)
- [Changelog](https://github.com/jonas-schievink/adler/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jonas-schievink/adler/compare/v0.2.2...v0.2.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-13 05:31:14 +00:00
dependabot-preview[bot]
cde162c62f build(deps): bump syn from 1.0.33 to 1.0.34
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.33 to 1.0.34.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.33...1.0.34)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-13 05:06:39 +00:00
dependabot-preview[bot]
8ab11ae87e build(deps): bump pkg-config from 0.3.17 to 0.3.18
Bumps [pkg-config](https://github.com/rust-lang/pkg-config-rs) from 0.3.17 to 0.3.18.
- [Release notes](https://github.com/rust-lang/pkg-config-rs/releases)
- [Changelog](https://github.com/rust-lang/pkg-config-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/pkg-config-rs/compare/0.3.17...0.3.18)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-13 05:05:29 +00:00
dependabot-preview[bot]
dda4cd8eb7 build(deps): bump redox_syscall from 0.1.56 to 0.1.57
Bumps redox_syscall from 0.1.56 to 0.1.57.

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-13 05:04:16 +00:00
Rob Bradford
4963e37dc8 qcow, virtio-devices: Break cyclic dependency
Move the definition of RawFile from virtio-devices crate into qcow
crate. All the code that consumes RawFile also already depends on the
qcow crate for image file type detection so this change breaks the
need for the qcow crate to depend on the very large virtio-devices
crate.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-10 17:47:31 +02:00
Rob Bradford
6161d3bef8 tests: Enable virtio-vsock testing with virtio-mmio transport
As compiling without acpi (implied by mmio) means that the VM will
terminate on i8042 reset we cannot test the reboot.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-10 07:22:37 +02:00
Rob Bradford
bb6b738c0d tests: Enable test_multiple_network_interfaces with virtio-mmio
Ensure that multiple network interfaces function correctly when using
virtio-mmio.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-09 09:53:30 +02:00
Rob Bradford
730f3884f4 tests: Enable test_virtio_blk with virtio-mmio transport
This test makes use of MQ support in virtio-block so it is advisable to
test with virtio-mmio.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-09 09:53:13 +02:00
Rob Bradford
d725c2cbfb tests: Enable virtio-mem testing with virtio-mmio
Try and enable virtio-mem testing when using the virtio-mmio transport.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-09 09:52:56 +02:00
dependabot-preview[bot]
96274a33ca build(deps): bump cc from 1.0.57 to 1.0.58
Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.57 to 1.0.58.
- [Release notes](https://github.com/alexcrichton/cc-rs/releases)
- [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.57...1.0.58)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-08 15:12:19 +00:00
Rob Bradford
f47f221f24 build: Remove obsolete feature differentiated vhost_user_net builds
Now that vhost_user_net crate does not depend on the virtio-devices
crate it is no longer compiled differently based on the mmio or pci
features.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-08 16:11:50 +01:00
Rob Bradford
17766fcea4 net_util, vhost_user_net, virtio-devices: Move NetQueuePair
Move NetQueuePair and the related NetCounters into the net_util crate.
This means that the vhost_user_net crate now no longer depends on
virtio-devices and so does not depend on the pci, qcow or other similar
crates. This significantly simplifies the build chain for this backend.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-08 16:11:50 +01:00
Rob Bradford
1237784a8f net_util, virtio-devices: Move TAP register/unregister helpers
Move these helper functions into net_util so that they can be used from
code inside there.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-08 16:11:50 +01:00
Rob Bradford
7f3e40e0cf net_util: Consolidate vnet_hdr_len() functions
As a result of refactoring this function was duplicated so consolidate
into the top level.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-08 16:11:50 +01:00
Rob Bradford
48faf3abac net_util, virtio-devices, vhost_user_net: Relocate {Rx,Tx}Virtio
By moving the code for opening the two RX and TX queues into a shared
location we are starting to remove the requirement for the
vhost-user-net backend to depend on the virtio-devices crate which in of
itself depends on many other crates that are not necessary for the
backend to function.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-08 16:11:50 +01:00
Rob Bradford
2efd307c4e net_util: Use two two different enums for MQ error
Rather than use an embedded String inside the MultiQueueSupport error
value use two different values to differentiate the two cases.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-08 16:11:50 +01:00
Rob Bradford
3e807a19b7 net_util, virtio-devices, vhost_user_net: Relocate code for opening TAP
By moving the code for opening the TAP device into a shared location we
are starting to remove the requirement for the vhost-user-net backend to
depend on the virtio-devices crate which in of itself depends on many
other crates that are not necessary for the backend to function.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-08 16:11:50 +01:00
dependabot-preview[bot]
bb390981a9 build(deps): bump kvm-ioctls from d094064 to 37953e9
Bumps [kvm-ioctls](https://github.com/cloud-hypervisor/kvm-ioctls) from `d094064` to `37953e9`.
- [Release notes](https://github.com/cloud-hypervisor/kvm-ioctls/releases)
- [Commits](d094064fef...37953e968b)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-08 12:53:00 +00:00
Wei Liu
5bfac796b3 build: add a default feature KVM
It gets bubbled all the way up from hypervsior crate to top-level
Cargo.toml.

Cloud Hypervisor can't function without KVM at this point, so make it
a default feature.

Fix all scripts that use --no-default-features.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-08 11:07:15 +01:00
dependabot-preview[bot]
861337cc6f build(deps): bump libc from 0.2.71 to 0.2.72
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.71 to 0.2.72.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.71...0.2.72)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-08 05:11:25 +00:00
Sebastien Boeuf
ef554ba13c ci: Increase time to stabilize memory measurement
Check if increasing the time after the VM is spawned help with getting
more stable numbers for the base PSS.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-07 19:36:12 +02:00
Hui Zhu
b59f231092 tests: Add integration test to test_memory_hotplug for virtio-balloon
Signed-off-by: Hui Zhu <teawater@antfin.com>
2020-07-07 17:25:13 +01:00
Hui Zhu
800220acbb virtio-balloon: Store the balloon size to support reboot
This commit store balloon size to MemoryConfig.
After reboot, virtio-balloon can use this size to inflate back to
the size before reboot.

Signed-off-by: Hui Zhu <teawater@antfin.com>
2020-07-07 17:25:13 +01:00
Sebastien Boeuf
50da100afd virtio-devices: Fix virtio-balloon device
The implementation of the virtio-balloon was slightly wrong as it was
generating the GPA (Guest Physical Address) from the PFN (Page Frame
Number) which was a u32. That means the GPA was created as a u32, and
later a cast was done to extend it to a u64 type. Unfortunately, by
doing so, the GPA was wrong if the value was supposedly more than 32
bits.

That's why the PFN is casted into a u64 before the GPA is generated,
which creates the GPA on 64 bits directly.

Additionally, this patch simplifies the process_queue() function,
relying on multiple vm-memory helpers.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-07 17:25:13 +01:00
Hui Zhu
8ffbc3d031 vmm: api: ch-remote: Add balloon to VmResizeData
Signed-off-by: Hui Zhu <teawater@antfin.com>
2020-07-07 17:25:13 +01:00
Hui Zhu
f729b25a10 openapi: Add MemoryConfig balloon
Add MemoryConfig balloon to vmm/src/api/openapi/cloud-hypervisor.yaml.

Signed-off-by: Hui Zhu <teawater@antfin.com>
2020-07-07 17:25:13 +01:00
Hui Zhu
8b6b97b86f vmm: Add virtio-balloon support
This commit adds new option balloon to memory config.
Set it to on will open the balloon function.

Signed-off-by: Hui Zhu <teawater@antfin.com>
2020-07-07 17:25:13 +01:00
Hui Zhu
0d72aa782f virtio-devices: Add virtio-balloon device
Add virtio-balloon device.
It only supports the basic functions of the virtio-balloon.

Signed-off-by: Hui Zhu <teawater@antfin.com>
2020-07-07 17:25:13 +01:00
dependabot-preview[bot]
ccc276a222 build(deps): bump backtrace from 0.3.49 to 0.3.50
Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.49 to 0.3.50.
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.49...0.3.50)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-07 14:40:07 +00:00
Henry Wang
603445e0a5 tests: Add a Jenkins stage for AArch64 integration test
This commit adds a Jenkins stage for AArch64 integration test,
and the test is carried out using the GNU toolchain.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-07-07 13:55:39 +01:00
Henry Wang
33c5d6bb98 tests: Enable test_aarch64_pe_boot case for AArch64
The compiled AArch64 linux kernel by running `make` is in PE format
instead of vmlinux, vmlinux.pvh and bzImage format. Therefore we
need to add integration test for this case.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-07-07 13:55:39 +01:00
Henry Wang
2ce231370d tests: Preparation of enabling integration tests for AArch64
This commit adds supporting components and code for enabling the
AArch64 integration tests, including:

1. A Linux kernel config file to build kernel on AArch64 machines.

2. Refactoring the `run_integration_test.sh` to architecture
specific scripts for readability.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-07-07 13:55:39 +01:00
Rob Bradford
b69f6d4f6c vhost_user_net, vhost_user_block, option_parser: Remove vmm dependency
Remove the vmm dependency from vhost_user_block and vhost_user_net where
it was existing to use config::OptionParser. By moving the OptionParser
to its own crate at the top-level we can remove the very heavy
dependency that these vhost-user backends had.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-06 18:33:29 +01:00
dependabot-preview[bot]
90261bb9c7 build(deps): bump smallvec from 1.4.0 to 1.4.1
Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.4.0 to 1.4.1.
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/compare/v1.4.0...v1.4.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-06 16:38:18 +00:00
Michael Zhao
726e45e0ce vmm: Divide Seccomp KVM IOCTL rules by architecture
Refactored the construction of KVM IOCTL rules for Seccomp.
Separating the rules by architecture can reduce the risk of bugs and
attacks.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-06 13:40:38 +01:00
Wei Liu
a4f484bc5e hypervisor: Define a VM-Exit abstraction
In order to move the hypervisor specific parts of the VM exit handling
path, we're defining a generic, hypervisor agnostic VM exit enum.

This is what the hypervisor's Vcpu run() call should return when the VM
exit can not be completely handled through the hypervisor specific bits.
For KVM based hypervisors, this means directly forwarding the IO related
exits back to the VMM itself. For other hypervisors that e.g. rely on the
VMM to decode and emulate instructions, this means the decoding itself
would happen in the hypervisor crate exclusively, and the rest of the VM
exit handling would be handled through the VMM device model implementation.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

Fix test_vm unit test by using the new abstraction and dropping some
dead code.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-06 12:59:43 +01:00
Wei Liu
cfa758fbb1 vmm, hypervisor: introduce and use make_user_memory_region
This removes the last KVM-ism from memory_manager. Also make use of that
method in other places.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-06 12:31:19 +02:00
Wei Liu
8d97d628c3 vmm: drop "kvm" from memory slot code
The code is purely for maintaining an internal counter. It is not really
tied to KVM.

No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-06 12:31:19 +02:00
Rob Bradford
f19f7490c6 build: Bulk upgrade dependencies
There are several dependencies that need updating so update them
manually rather than relying on dependabot. This will reduce the load on
the CI.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-06 10:46:17 +01:00
Rob Bradford
72802b34cd vhost_user_block: Move binary into vhost_user_block crate
The binary is still built in the same location but the source code and
the dependencies for it come from the vhost_user_block crate itself.

The binary will be built with:

`cargo build --all --bin vhost_user_block` or just `cargo build --all`

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-06 10:56:10 +02:00
Rob Bradford
6959d27e8c vhost_user_net: Move binary into vhost_user_net crate
The binary is still built in the same location but the source code and
the dependencies for it come from the vhost_user_net crate itself.

The binary will be built with:

`cargo build --all --bin vhost_user_net` or just `cargo build --all`

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-06 10:56:10 +02:00
Rob Bradford
7548283feb build: Remove unused dependencies from top-level Cargo.toml
With vhost_user_fs binary moved to its own crate the dependencies in the
top level can be trimmed significantly.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-06 10:56:10 +02:00
Rob Bradford
d6a05ceabb vhost_user_fs: Move binary into vhost_user_fs crate
The binary is still built in the same location but the source code and
the dependencies for it come from the vhost_user_fs crate itself.

The binary will be built with:

`cargo build --all --bin vhost_user_fs` or just `cargo build --all`

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-06 10:56:10 +02:00
Rob Bradford
b8be6bab16 tests: Prepare for splitting binaries by building all binaries
In preparation for splitting the binaries into their own crates start
building all the binaries in the workspace as part of the integration
testing suite.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-06 10:56:10 +02:00
Rob Bradford
6f59cdbb55 build: dev_cli: Prepare for splitting binaries by building all binaries
In preparation for splitting the binaries into their own crates start
building all the binaries in the workspace when running the build
command inside the container.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-06 10:56:10 +02:00
Rob Bradford
1e9956c8cb build: github: Prepare for splitting binaries by building all binaries
In preparation for splitting the binaries into their own crates start
building all the binaries in the workspace when doing a build as part of
the GitHub actions.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-06 10:56:10 +02:00
dependabot-preview[bot]
863ea97213 build(deps): bump vfio-ioctls from f6f81ee to 4c56812
Bumps [vfio-ioctls](https://github.com/cloud-hypervisor/vfio-ioctls) from `f6f81ee` to `4c56812`.
- [Release notes](https://github.com/cloud-hypervisor/vfio-ioctls/releases)
- [Commits](f6f81ee865...4c568127fe)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-06 08:45:57 +00:00
Samuel Ortiz
8186a8eee6 vmm: interrupt: Rename vm_fd
The _fd suffix is KVM specific. But since it now point to an hypervisor
agnostic hypervisor::Vm implementation, we should just rename it vm.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-07-06 09:35:30 +01:00
Samuel Ortiz
4cc8853fe4 vmm: device_manager: Rename vm_fd
The _fd suffix is KVM specific. But since it now point to an hypervisor
agnostic hypervisor::Vm implementation, we should just rename it vm.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-07-06 09:35:30 +01:00
Samuel Ortiz
2012287611 vmm: memory_manager: Rename fd variable into something more meaningful
The fd naming is quite KVM specific. Since we're now using the
hypervisor crate abstractions, we can rename those into something more
readable and meaningful.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-07-06 09:35:30 +01:00
Samuel Ortiz
acfe5eb94f vmm: vm: Rename fd variable into something more meaningful
The fd naming is quite KVM specific. Since we're now using the
hypervisor crate abstractions, we can rename those into something more
readable and meaningful.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-07-06 09:35:30 +01:00
Samuel Ortiz
3db4c003a3 vmm: cpu: Rename fd variable into something more meaningful
The fd naming is quite KVM specific. Since we're now using the
hypervisor crate abstractions, we can rename those into something more
readable and meaningful. Like e.g. vcpu or vm.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-07-06 09:35:30 +01:00
Samuel Ortiz
618722cdca hypervisor: cpu: Rename state getter and setter
vcpu.{set_}cpu_state() is a stutter.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-07-06 09:35:30 +01:00
Sebastien Boeuf
a3342bdb25 docs: Replace every mention of ClearLinux with Ubuntu
Now that our CI has transitioned from ClearLinux to Ubuntu images
exclusively, let's update the documentation to refer to Ubuntu images
instead of ClearLinux's ones.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-03 14:37:09 +02:00
Sebastien Boeuf
b452e8be00 docs: Update custom image instructions
Now that the project relies on Ubuntu images, the documentation related
to the creation of a custom image has been updated. It's important to
note this procedure could be applied to any other distribution, given
that the package manager's commands would be slightly different.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-03 14:37:09 +02:00
Sebastien Boeuf
bb9174601a ci: Separate parallel vs sequential tests
In order to differentiate tests that can be run in parallel versus
tests that must be run on their own, we move all tests into dedicated
modules.

The point is to avoid glitches in results that can be caused by the fact
that other tests (hence VMs) are running at the same time.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-03 13:08:37 +01:00
Rob Bradford
2a6eb31d5b vm-virtio, virtio-devices: Split device implementation from virt queues
Split the generic virtio code (queues and device type) from the
VirtioDevice trait, transport and device implementations.

This also simplifies the feature handling in vhost_user_backend as the
vm-virtio crate is no longer has any features.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-02 17:09:28 +01:00
dependabot-preview[bot]
9a628edfcf build(deps): bump cc from 1.0.56 to 1.0.57
Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.56 to 1.0.57.
- [Release notes](https://github.com/alexcrichton/cc-rs/releases)
- [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.56...1.0.57)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-02 14:40:59 +00:00
Wei Liu
44be3af9c8 arch: drop one level of indirection for boot_msr_entries
This makes setup_msrs hypervisor agnostic.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-07-02 13:47:58 +02:00
Sebastien Boeuf
c2920d2b6b ci: Move from Clear Linux to Ubuntu Focal Fossa cloud image
Move the CI to rely entirely on Ubuntu cloud images. It's worth noting
that both QCOW2 and RAW images from Ubuntu Focal Fossa have been
modified to include the tools needed from integration tests.
This means fio, iperf, iperf3, netcat and socat have been added to the
image. The snapd package have been fully removed as it was expecting the
support for squashfs (not present when using our own kernel from direct
kernel boot), which was causing some failures, and was preventing
cloud-init from terminating properly.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-02 13:47:16 +02:00
Sebastien Boeuf
1f9103bb67 test_data: Update Ubuntu cloud-init to support all integration tests
Updating the cloud-init files related to Ubuntu images is needed to be
able to use Ubuntu images for running all integration tests.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-07-02 13:47:16 +02:00
Rob Bradford
135ee4568e tests: Enhance rate_limited_copy() to also consider free disk space
With QCOW disk images the space needed is greater than the size of the
iamge as any "zero" blocks in the image are allocated when they are
touched making the image bigger.

Here we add a threshold of 6GiB with added debugging messages to ensure
that there is sufficient disk space to run the tests.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-02 11:52:49 +02:00
Michael Zhao
8820e9e133 vmm: Fix Seccomp filter for AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2020-07-02 08:46:24 +01:00
Rob Bradford
8e43f886e1 build: Bump kvm-ioctls dependency after rebase
ch branch is now rebased on latest upstream master

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-07-01 18:46:05 +02:00
Henry Wang
b70e254700 resources: Dockerfile: Update Dockerfile for AArch64
This update of Dockerfile will add support to the AArch64
integration tests and musl building, including:

1. Installation of the missing `setcap` binary on AArch64.
On AArch64, `setcap` binary should be installed via `libcap2-bin`.
This binary is needed in the integration test.

2. Related support for the cloud-hypervisor binary building by
musl toolchain.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-07-01 09:51:15 +01:00
Wei Liu
92a62d80e9 README: update hypervisor-fw release
The CI is using 0.2.8.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-30 21:02:13 +01:00
Rob Bradford
f8a8a5ca68 arch: x86_64: Remove residual debugging from smbios code
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-30 15:50:33 +01:00
Rob Bradford
602f76e4fc arch: x86_64: Use symbolic constant for end of table
The other types use a symbolic constant so do the same for consistency.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-30 15:50:33 +01:00
Sebastien Boeuf
514978b54a ci: Improve test_snapshot_restore with multiple vCPUs
Extend the existing integration test test_snapshot_restore by testing
with more than one vCPU.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-30 14:03:03 +01:00
Sebastien Boeuf
e35d4c5b28 hypervisor: Store all supported MSRs
On x86 architecture, we need to save a list of MSRs as part of the vCPU
state. By providing the full list of MSRs supported by KVM, this patch
fixes the remaining snapshot/restore issues, as the vCPU is restored
with all its previous states.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-30 14:03:03 +01:00
Sebastien Boeuf
49b4fba283 hypervisor: Retrieve list of supported MSRs
Add a new function to the hypervisor trait so that the caller can
retrieve the list of MSRs supported by this hypervisor.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-30 14:03:03 +01:00
Sebastien Boeuf
e2b5c78dc5 hypervisor: Re-order vCPU state for storing and restoring
Some vCPU states such as MP_STATE can be modified while retrieving
other states. For this reason, it's important to follow a specific
order that will ensure a state won't be modified after it has been
saved. Comments about ordering requirements have been copied over
from Firecracker commit 57f4c7ca14a31c5536f188cacb669d2cad32b9ca.

This patch also set the previously saved VCPU_EVENTS, as this was
missing from the restore codepath.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-30 14:03:03 +01:00
Wei Liu
2b8accf49a vmm: interrupt: put KVM code into a kvm module
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-30 12:09:42 +01:00
Wei Liu
c31e747005 vmm: interrupt: generify impl InterruptManager for MsiInterruptManager
The logic can be shared among hypervisor implementations.

The 'static bound is used such that we don't need to deal with extra
lifetime parameter everywhere. It should be okay because we know the
entry type E doesn't contain any reference.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-30 12:09:42 +01:00
Wei Liu
ade904e356 vmm: interrupt: generify impl InterruptSourceGroup for MsiInterruptGroup
At this point we can use the same logic for all hypervisor
implementations.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-30 12:09:42 +01:00
Wei Liu
2b466ed80c vmm: interrupt: provide MsiInterruptGroupOps trait
Currently it only contains a function named set_gsi_routes.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-30 12:09:42 +01:00
Wei Liu
b2abead65b vmm: interrupt: provide and use extension trait RoutingEntryExt
This trait contains a function which produces a interrupt routing entry.

Implement that trait for KvmRoutingEntry and rewrite the update
function.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-30 12:09:42 +01:00
Wei Liu
4dbca81b86 vmm: interrupt: rename set_kvm_gsi_routes to set_gsi_routes
This function will be used to commit routing information to the
hypervisor.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-30 12:09:42 +01:00
Wei Liu
fd7b42e54d vmm: interrupt: inline mask_kvm_entry
The logic for looking up the correct interrupt can be shared among
hypervisors.

No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-30 12:09:42 +01:00
Wei Liu
0ec39da90c vmm: interrupt: generify KvmMsiInterruptManager
The observation is only the route entry is hypervisor dependent.

Keep a definition of KvmMsiInterruptManager to avoid too much code
churn.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-30 12:09:42 +01:00
Wei Liu
d5149e95cb vmm: interrupt: generify KvmRoutingEntry and KvmMsiInterruptGroup
The observation is that only the route field is hypervisor specific.

Provide a new function in blanket implementation. Also redefine
KvmRoutingEntry with RoutingEntry to avoid code churn.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-30 12:09:42 +01:00
Wei Liu
637f58bcd9 vmm: interrupt: drop Kvm prefix from KvmLegacyUserspaceInterruptManager
This data structure doesn't contain KVM specific stuff.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-30 12:09:42 +01:00
Wei Liu
574cab6990 vmm: interrupt: create GSI hashmap directly
The observation is that the GSI hashmap remains untouched before getting
passed into the MSI interrupt manager. We can create that hashmap
directly in the interrupt manager's new function.

The drops one import from the interrupt module.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-30 12:09:42 +01:00
dependabot-preview[bot]
f3c8f827cc build(deps): bump linux-loader from 2a62f21 to ec930d7
Bumps [linux-loader](https://github.com/rust-vmm/linux-loader) from `2a62f21` to `ec930d7`.
- [Release notes](https://github.com/rust-vmm/linux-loader/releases)
- [Commits](2a62f21b44...ec930d700f)

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-30 07:05:06 +00:00
Rob Bradford
fbbe348447 arch: x86-64: Add missing End of Table entry
The OVMF firmware loops around looking for an entry marking the end of
the table. Without this entry processing the tables is an infinite loop.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-30 08:15:48 +02:00
Rob Bradford
2c3c335de6 arch: x86_64: Add basic SMBIOS support
Taken from crosvm: 44336b913126d73f9f8d6854f57aac92b5db809e and adapted
for Cloud Hypervisor.

This is basic and incomplete support but Linux correctly finds the DMI
data based on this:

root@clr-c6ed47bc1c9d473d9a3a8bddc50ee4cb ~ # dmesg | grep -i dmi
[    0.000000] DMI: Cloud Hypervisor cloud-hypervisor, BIOS 0

root@clr-c6ed47bc1c9d473d9a3a8bddc50ee4cb ~ # dmesg | grep -i smbio
[    0.000000] SMBIOS 3.2.0 present.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-30 08:15:48 +02:00
Wei Liu
24c051c663 vmm: hypervisor: drop duplicate comment
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-29 21:51:59 +01:00
Wei Liu
2518b9e3cd vmm: hypervisor: fix white space issues
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-29 21:51:59 +01:00
dependabot-preview[bot]
5ac3299234 build(deps): bump serde_json from 1.0.55 to 1.0.56
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.55 to 1.0.56.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.55...v1.0.56)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-29 19:54:47 +00:00
dependabot-preview[bot]
58980067f4 build(deps): bump ssh2 from 0.8.1 to 0.8.2
Bumps [ssh2](https://github.com/alexcrichton/ssh2-rs) from 0.8.1 to 0.8.2.
- [Release notes](https://github.com/alexcrichton/ssh2-rs/releases)
- [Commits](https://github.com/alexcrichton/ssh2-rs/compare/0.8.1...0.8.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-29 18:02:38 +00:00
dependabot-preview[bot]
d2780a6575 build(deps): bump unicode-width from 0.1.7 to 0.1.8
Bumps [unicode-width](https://github.com/unicode-rs/unicode-width) from 0.1.7 to 0.1.8.
- [Release notes](https://github.com/unicode-rs/unicode-width/releases)
- [Commits](https://github.com/unicode-rs/unicode-width/commits/v0.1.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-29 17:37:40 +00:00
Samuel Ortiz
5a6b8d6323 dev_cli: Add a shell command
And drop the caller into a privileged root shell.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-06-29 18:17:39 +01:00
Henry Wang
d824d55562 unit tests: Fix broken AArch64 unit tests
https://github.com/cloud-hypervisor/cloud-hypervisor/pull/1225
introduces a hypervisor abstraction crate, which breaks some of
the unit test cases on AArch64. This commit fixes related test
cases.

Signed-off-by: Henry Wang <henry.wang@arm.com>
2020-06-29 18:00:42 +01:00
Henry Wang
462c58d58b tests: Enable AArch64 Jenkins CI with unit tests for GNU
This commit enables the AArch64 Jenkins CI with build and running
unit tests for GNU toolchain.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-06-29 18:00:42 +01:00
dependabot-preview[bot]
ba3f1bcde2 build(deps): bump cc from 1.0.55 to 1.0.56
Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.55 to 1.0.56.
- [Release notes](https://github.com/alexcrichton/cc-rs/releases)
- [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.55...1.0.56)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-29 16:20:33 +00:00
Rob Bradford
6ee9903601 docs: Update API documentation
Update the API documentation to reflect that the hotplug APIs return
data about the device as well as the newly added /vm.counters API.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-27 00:07:47 +02:00
Rob Bradford
522d8c8412 vmm: openapi: Add the /vm.counters API entry point
This is a hash table of string to hash tables of u64s. In JSON these
hash tables are object types.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-27 00:07:47 +02:00
Muminul Islam
72ae1577ed hypervisor: Update license to Apache-2.0 OR BSD-3-Clause
Initially the licensing was just Apache-2.0. This patch changes
the licensing to dual license Apache-2.0 OR BSD-3-Clause

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-06-27 00:06:39 +02:00
dependabot-preview[bot]
e1ea06e74a build(deps): bump cc from 1.0.54 to 1.0.55
Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.54 to 1.0.55.
- [Release notes](https://github.com/alexcrichton/cc-rs/releases)
- [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.54...1.0.55)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-26 04:55:46 +00:00
dependabot-preview[bot]
19ce0a37a4 build(deps): bump epoll from 4.3.0 to 4.3.1
Bumps [epoll](https://github.com/nathansizemore/epoll) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/nathansizemore/epoll/releases)
- [Commits](https://github.com/nathansizemore/epoll/commits/4.3.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-25 14:03:04 +00:00
Sebastien Boeuf
a7f0f9dfea vm-virtio: Ensure pause event is caught by every virtio thread
Each virtio thread was reading/draining the pause_evt pipe when
detecting the associated event. Problem is, when a virtio device has
multiple threads, they all share the same pause_evt pipe, which can
prevent some threads from receiving the event. If the first thread to
catch the event is quickly clearing the pipe, some other threads might
simply miss the event and they will not enter the "paused" state as
expected.

This is a behavior that was spotted with virtio-net as it usually uses
2 threads by default (1 for TX/RX queues and 1 for the control queue).

The way to solve this issue is by letting each thread drain the pipe
during the resume codepath, that is after the thread has been unparked.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-25 12:01:34 +02:00
Sebastien Boeuf
86377127df vmm: Resume devices after vCPUs have been resumed
Because we don't want the guest to miss any event triggered by the
emulation of devices, it is important to resume all vCPUs before we can
resume the DeviceManager with all its associated devices.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-25 12:01:34 +02:00
Sebastien Boeuf
f6eeba781b vmm: Save and restore vCPU states during pause/resume operations
We need consistency between pause/resume and snapshot/restore
operations. The symmetrical behavior of pausing/snapshotting
and restoring/resuming has been introduced recently, and we must
now ensure that no matter if we're using pause/resume or
snapshot/restore features, the resulting VM should be running in
the exact same way.

That's why the vCPU state is now stored upon VM pausing. The snapshot
operation being a simple serialization of the previously saved state.
The same way, the vCPU state is now restored upon VM resuming. The
restore operation being a simple deserialization of the previously
restored state.

It's interesting to note that this patch ensures time consistency from a
guest perspective, no matter which clocksource is being used. From a
previous patch, the KVM clock was saved/restored upon VM pause/resume.
We now have the same behavior for TSC, as the TSC from the vCPUs are
saved/restored upon VM pause/resume too.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-25 12:01:34 +02:00
Sebastien Boeuf
18e7d7a1f7 vmm: cpu: Resume before shutdown in a specific way
Instead of calling the resume() function from the CpuManager, which
involves more than what is needed from the shutdown codepath, and
potentially ends up with a deadlock, we replace it with a subset.

The full resume operation is reserved for a VM that has been paused.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-25 12:01:34 +02:00
Sebastien Boeuf
65132fb99d vmm: Implement Pausable trait for Vcpu
We want each Vcpu to store the vCPU state upon VM pausing. This is the
reason why we need to explicitly implement the Pausable trait for the
Vcpu structure.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-25 12:01:34 +02:00
Wei Liu
1741af74ed hypervisor: add safety statement in set_user_memory_region
When set_user_memory_region was moved to hypervisor crate, it was turned
into a safe function that wrapped around an unsafe call. All but one
call site had the safety statements removed. But safety statement was
not moved inside the wrapper function.

Add the safety statement back to help reasoning in the future. Also
remove that one last instance where the safety statement is not needed .

No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-25 10:25:13 +02:00
Wei Liu
b27439b6ed arch, hypervisor, vmm: KvmHyperVisor -> KvmHypervisor
"Hypervisor" is one word. The "v" shouldn't be capitalised.

No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-25 10:25:13 +02:00
Wei Liu
b00171e17d vmm: use MemoryRegion where applicable
That removes one more KVM-ism in VMM crate.

Note that there are more KVM specific code in those files to be split
out, but we're not at that stage yet.

No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-25 10:25:13 +02:00
Rob Bradford
48a05c4727 tests: Add simple counters integration test
Add a simple test to check that the data from the counters matches what
is expected and that the value of the counters increases after an
operation that will hit all counters.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-25 07:02:44 +02:00
Rob Bradford
980b49da94 vm-virtio: block: Implement counters for block device
Expose counters for read/write bytes/ops from the virtio block device.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-25 07:02:44 +02:00
Rob Bradford
d983c0a680 vmm: Expose counters from virtio devices to API
Collate the virtio device counters in DeviceManager for each device that
exposes any and expose it through the recently added HTTP API.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-25 07:02:44 +02:00
Rob Bradford
9b7afd4aac bin: ch-remote: Implement "counters" command
This is used to obtain the counters from the VM. The raw JSON data is
presented to the user.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-25 07:02:44 +02:00
Rob Bradford
bca8a19244 vmm: Implement HTTP API for obtaining counters
The counters are a hash of device name to hash of counter name to u64
value. Currently the API is only implemented with a stub that returns an
empty set of counters.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-25 07:02:44 +02:00
Rob Bradford
fd4aba8eae vmm: api: Implement support for GET handlers EndpointHandler
This can be used for simple API requests which return data but do not
require any input.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-25 07:02:44 +02:00
Rob Bradford
80be393b16 vmm: api: Order HTTP entry points in alphabetical order
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-25 07:02:44 +02:00
Rob Bradford
6713a3c859 vm-virtio: net: Expose network counters through VirtioDevice
Through the counters() function on the trait expose the accumulated
counters.

TEST=Observe that the counters from the VM match those from the tap on
the host (RX-TX inverted) and inside the guest (non inverted.)

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-25 07:02:44 +02:00
Rob Bradford
dd54883a07 vm-virtio: device: Extend the VirtioDevice trait to expose counters
The counters are a hash of counter name to (wrapping) u64 value. The
interpretation layer is responsible for converting this data into a
rate.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-25 07:02:44 +02:00
Rob Bradford
2b4a0358de vm-virtio: net: Implement counters for network traffic
Add counters for RX/TX bytes and RX/TX frames. These are collected on a
per queue basis and then accumulated into an atomic shared value across
the different threads for the device as a whole.

Collecting and accumulating these counters makes minimal difference in
the iperf results. Any difference seen is within what is observed as
natural variation in this test.

e.g.

With counter updates:

$ iperf3 -c 192.168.249.2
Connecting to host 192.168.249.2, port 5201
[  5] local 192.168.249.1 port 52706 connected to 192.168.249.2 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  6.19 GBytes  53.2 Gbits/sec    0   3.01 MBytes
[  5]   1.00-2.00   sec  6.31 GBytes  54.2 Gbits/sec    0   3.01 MBytes
[  5]   2.00-3.00   sec  6.29 GBytes  54.0 Gbits/sec    0   3.01 MBytes
[  5]   3.00-4.00   sec  6.22 GBytes  53.4 Gbits/sec    0   3.01 MBytes
[  5]   4.00-5.00   sec  6.14 GBytes  52.8 Gbits/sec    0   3.01 MBytes
[  5]   5.00-6.00   sec  6.13 GBytes  52.7 Gbits/sec    0   3.01 MBytes
[  5]   6.00-7.00   sec  6.20 GBytes  53.3 Gbits/sec    0   3.01 MBytes
[  5]   7.00-8.00   sec  6.16 GBytes  52.9 Gbits/sec    0   3.01 MBytes
[  5]   8.00-9.00   sec  6.13 GBytes  52.6 Gbits/sec    0   3.01 MBytes
[  5]   9.00-10.00  sec  6.15 GBytes  52.8 Gbits/sec    0   3.01 MBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  61.9 GBytes  53.2 Gbits/sec    0             sender
[  5]   0.00-10.00  sec  61.9 GBytes  53.2 Gbits/sec                  receiver

iperf Done.

Without counter updates:

$ iperf3 -c 192.168.249.2
Connecting to host 192.168.249.2, port 5201
[  5] local 192.168.249.1 port 52716 connected to 192.168.249.2 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  6.29 GBytes  54.1 Gbits/sec    0   3.03 MBytes
[  5]   1.00-2.00   sec  6.18 GBytes  53.1 Gbits/sec    0   3.03 MBytes
[  5]   2.00-3.00   sec  6.26 GBytes  53.8 Gbits/sec    0   3.03 MBytes
[  5]   3.00-4.00   sec  6.24 GBytes  53.6 Gbits/sec    0   3.03 MBytes
[  5]   4.00-5.00   sec  6.27 GBytes  53.9 Gbits/sec    1   3.03 MBytes
[  5]   5.00-6.00   sec  6.31 GBytes  54.2 Gbits/sec    0   3.03 MBytes
[  5]   6.00-7.00   sec  6.29 GBytes  54.1 Gbits/sec    0   3.03 MBytes
[  5]   7.00-8.00   sec  6.16 GBytes  52.9 Gbits/sec    0   3.03 MBytes
[  5]   8.00-9.00   sec  6.13 GBytes  52.6 Gbits/sec    0   3.03 MBytes
[  5]   9.00-10.00  sec  6.25 GBytes  53.7 Gbits/sec    0   3.03 MBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  62.4 GBytes  53.6 Gbits/sec    1             sender
[  5]   0.00-10.00  sec  62.4 GBytes  53.6 Gbits/sec                  receiver

iperf Done.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-25 07:02:44 +02:00
Dr. David Alan Gilbert
0583ce921b vhost_user_fs: Allow fchmod in seccomp
This corresponds to QEMU's 63659fe74e76f5c52854 commit.
the setattr code uses both fchmod and fchmodat in different cases,
however we only had fchmodat in the whitelist.

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
2020-06-24 21:56:58 +01:00
Wei Liu
4cc37d7b9a vmm: interrupt: drop a few pub keywords
Those items are not used elsewhere. Restrict their scope.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-24 12:39:42 +02:00
Wei Liu
1661adbbaf vmm: interrupt: add "Kvm" prefix to MsiInterruptGroup
The structure is tightly coupled with KVM. It uses KVM specific
structures and calls. Add Kvm prefix to it.

Microsoft hypervisor will implement its own interrupt group(s) later.

No functional change intended.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-24 12:39:42 +02:00
Sebastien Boeuf
9f4714c32a vmm: Extend seccomp filters with KVM_KVMCLOCK_CTRL
Now that the VMM uses KVM_KVMCLOCK_CTRL from the KVM API, it must be
added to the seccomp filters list.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-24 12:38:56 +02:00
Sebastien Boeuf
4a81d65f79 vmm: Notify the guest about vCPUs being paused
Through the newly added API notify_guest_clock_paused(), this patch
improves the vCPU pause operation by letting the guest know that each
vCPU is being paused. This is important to avoid soft lockups detection
from the guest that could happen because the VM has been paused for more
than 20 seconds.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-24 12:38:56 +02:00
Sebastien Boeuf
309924eca8 hypervisor: Add guest pause notification
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-24 12:38:56 +02:00
Sebastien Boeuf
9fa8438063 vmm: Fill CpuManager's vCPU list on restore path
It's important that on restore path, the CpuManager's vCPU gets filled
with each new vCPU that is being created. In order to cover both boot
and restore paths, the list is being filled from the common function
create_vcpu().

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-24 12:38:56 +02:00
Sebastien Boeuf
0b45f6364e build(deps): Update to latest kvm-ioctls
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-24 12:38:56 +02:00
dependabot-preview[bot]
7f955ff122 build(deps): bump epoll from 4.2.0 to 4.3.0
Bumps [epoll](https://github.com/nathansizemore/epoll) from 4.2.0 to 4.3.0.
- [Release notes](https://github.com/nathansizemore/epoll/releases)
- [Commits](https://github.com/nathansizemore/epoll/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-24 05:39:26 +00:00
Sebastien Boeuf
f5150aa261 vmm: Extend seccomp filters with KVM_GET_CLOCK and KVM_SET_CLOCK
Now that the VMM uses both KVM_GET_CLOCK and KVM_SET_CLOCK from the KVM
API, they must be added to the seccomp filters list.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-23 14:36:01 +01:00
Sebastien Boeuf
8038161861 vmm: Get and set clock during pause and resume operations
In order to maintain correct time when doing pause/resume and
snapshot/restore operations, this patch stores the clock value
on pause, and restore it on resume. Because snapshot/restore
expects a VM to be paused before the snapshot and paused after
the restore, this covers the migration use case too.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-23 14:36:01 +01:00
Sebastien Boeuf
68ec0eb7a8 hypervisor: Add get/set clock API
Add the hypervisor wrappers to expose KVM_GET_CLOCK and KVM_SET_CLOCK
from the KVM API.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-23 14:36:01 +01:00
Rob Bradford
4b64f2a027 vmm: cpu: Reuse already allocated vCPUs if available
When a request is made to increase the number of vCPUs in the VM attempt
to reuse any previously removed (and hence inactive) vCPUs before
creating new ones.

This ensures that the APIC ID is not reused for a different KVM vCPU
(which is not allowed) and that the APIC IDs are also sequential.

The two key changes to support this are:

* Clearing the "kill" bit on the old vCPU state so that it does not
  immediately exit upon thread recreation.
* Using the length of the vcpus vector (the number of allocated vcpus)
  rather than the number of active vCPUs (.present_vcpus()) to determine
  how many should be created.

This change also introduced some new info!() debugging on the vCPU
creation/removal path to aid further development in the future.

TEST=Expanded test_cpu_hotplug test.

Fixes: #1338

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-23 14:11:14 +01:00
Rob Bradford
9dcd0c37f3 vmm: cpu: Clear the "kill" flag on vCPU to support reuse
After the vCPU has been ejected and the thread shutdown it is useful to
clear the "kill" flag so that if the vCPU is reused it does not
immediately exit upon thread recreation.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-23 14:11:14 +01:00
Rob Bradford
b107bfcf2c vmm: cpu: Add info!() level debugging to vCPU handling
These messages are intended to be useful to support debugging related to
vCPU hotplug/unplug issues.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-23 14:11:14 +01:00
dependabot-preview[bot]
3c2bfbdc95 build(deps): bump aho-corasick from 0.7.12 to 0.7.13
Bumps [aho-corasick](https://github.com/BurntSushi/aho-corasick) from 0.7.12 to 0.7.13.
- [Release notes](https://github.com/BurntSushi/aho-corasick/releases)
- [Commits](https://github.com/BurntSushi/aho-corasick/compare/0.7.12...0.7.13)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-23 13:03:45 +00:00
Sebastien Boeuf
b5cf150ac3 ci: Update test_snapshot_restore by resuming the VM
Now that snapshot/restore is symmetrical, that is the VM must be paused
before it is snapshot and it must be resumed after it's been restored,
the integration test is updated accordingly.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-23 10:15:03 +02:00
Sebastien Boeuf
e382dc6657 vmm, vm-virtio: Restore DeviceManager's devices in a paused state
The same way the VM and the vCPUs are restored in a paused state, all
devices associated with the device manager must be restored in the same
paused state.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-23 10:15:03 +02:00
Sebastien Boeuf
8a165b5314 vmm: Restore the VM in "paused" state
Because we need to pause the VM before it is snapshot, it should be
restored in a paused state to keep the sequence symmetrical. That's the
reason why the state machine regarding the valid VM's state transition
needed to be updated accordingly.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-23 10:15:03 +02:00
Sebastien Boeuf
a16414dc87 vmm: Restore vCPUs in "paused" state
To follow a symmetrical model, and avoid potential race conditions, it's
important to restore a previously snapshot VM in a "paused" state.

The snapshot operation being valid only if the VM has been previously
paused.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-23 10:15:03 +02:00
Wei Liu
7552f4db61 vmm: device_manager: restore error handling
When the hypervisor crate was introduced, a few places that handled
errors were commented out in favor of unwrap, but that's bad practice.

Restore proper error handling in those places in this patch.

We cannot use from_raw_os_error anymore because it is wrapped deep under
hypervisor crate. Create new custom errors instead.

Fixes: e4dee57e81 ("arch, pci, vmm: Initial switch to the hypervisor crate")
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-22 22:02:21 +01:00
Muminul Islam
cca59bc52f hypervisor, arch: Fix warnings introduced in hypervisor crate
This commit fixes some warnings introduced in the previous
hyperviosr crate PR.Removed some unused variables from arch/aarch64
module.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-06-22 21:58:45 +01:00
dependabot-preview[bot]
4ce7af08d8 build(deps): bump aho-corasick from 0.7.10 to 0.7.12
Bumps [aho-corasick](https://github.com/BurntSushi/aho-corasick) from 0.7.10 to 0.7.12.
- [Release notes](https://github.com/BurntSushi/aho-corasick/releases)
- [Commits](https://github.com/BurntSushi/aho-corasick/compare/0.7.10...0.7.12)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-22 21:57:15 +01:00
Rob Bradford
d714efe6d4 vmm: cpu: Import CpuTopology conditionally on x86_64 only
The aarch64 build has no use for this structure at the moment.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-22 15:00:27 +01:00
Sebastien Boeuf
a998e89375 build(deps): bump signal-hook from 0.1.15 to 0.1.16
Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.1.15
to 0.1.16.
- [Release notes](https://github.com/vorner/signal-hook/releases)
- [Changelog](https://github.com/vorner/signal-hook/blob/master/CHANGELOG.md)
- [Commits](vorner/signal-hook@v0.1.15...v0.1.16)

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-22 14:09:11 +01:00
Muminul Islam
e4dee57e81 arch, pci, vmm: Initial switch to the hypervisor crate
Start moving the vmm, arch and pci crates to being hypervisor agnostic
by using the hypervisor trait and abstractions. This is not a complete
switch and there are still some remaining KVM dependencies.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-06-22 15:03:15 +02:00
Muminul Islam
c48d0c1a67 hypervisor: kvm: Implement vCPU state method
Implement the vCPU state getter and setter separately from the initial
KVM Hypervisor trait implementation, mostly for readability purposes.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-06-22 15:03:15 +02:00
Muminul Islam
72e39a3496 hypervisor: Add KVM implementation
For each of the traits we are defining kvm related structures
and add the trait implementation to the structs. For more information
please see the kvm-ioctls and kvm-bindings crate.

This is a standalone implementation that does not include the switch of
the Cloud-Hypervisor vmm and arch crates to it.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-06-22 15:03:15 +02:00
Muminul Islam
683210d6e9 hypervisor: Add Hypervisor trait
As the only hypervisor that Cloud-Hypervisor supports is KVM, the
Hypervisor trait accomodates for the upcoming KVM implementation.

This trait will be instanciated at build time through hypervisor
specific features, i.e. it's not aiming at run-time selection of
hypervisors for Cloud-Hypervisor.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-06-22 15:03:15 +02:00
Muminul Islam
f5afc288d8 hypervisor: Add Vm trait
This VM trait should be implemented by each underlying hypervisor.

Previously created hypervisor object should create the VM based on
already selected hypervisor. This is just the trait definition. For each
of supported hypervisor we need to implement the trait. Later we will
implement this trait for KVM and then Microsoft Hyper-V.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-06-22 15:03:15 +02:00
Muminul Islam
f9b51a41b5 hypervisor: Add Vcpu trait
This Vcpu trait should be implemented by each underlying hypervisor.

Previously created hypervisor object should create the VM based on
already selected hypervisor and Vm object should create this vcpu
object based on same hyperviosr. Each of this object should be
referenced by trait object i.e <dyn Vcpu>.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2020-06-22 15:03:15 +02:00
Muminul Islam
56a1638517 hypervisor: Introduce hypervisor crate
The purpose of this trait is to add support for other hypervisors than
KVM, like e.g. Microsoft Hyper-V.

Further commits will define additional hypervisor related traits like
Vcpu and Vm. Each of the supported hypervisor will need to implement all
traits defined from the hypervisor crate.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2020-06-22 15:03:15 +02:00
dependabot-preview[bot]
b969d92fe3 build(deps): bump serde from 1.0.113 to 1.0.114
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.113 to 1.0.114.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.113...v1.0.114)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-22 06:03:59 +00:00
dependabot-preview[bot]
30fb6732a2 build(deps): bump serde_derive from 1.0.113 to 1.0.114
Bumps [serde_derive](https://github.com/serde-rs/serde) from 1.0.113 to 1.0.114.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.113...v1.0.114)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-22 05:18:53 +00:00
dependabot-preview[bot]
22fc3bfaaf build(deps): bump syn from 1.0.32 to 1.0.33
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.32 to 1.0.33.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.32...1.0.33)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-22 05:18:24 +00:00
dependabot-preview[bot]
c0d42dc1bf build(deps): bump syn from 1.0.31 to 1.0.32
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.31 to 1.0.32.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.31...1.0.32)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-21 18:09:04 +00:00
dependabot-preview[bot]
3a102c6573 build(deps): bump addr2line from 0.12.1 to 0.12.2
Bumps [addr2line](https://github.com/gimli-rs/addr2line) from 0.12.1 to 0.12.2.
- [Release notes](https://github.com/gimli-rs/addr2line/releases)
- [Changelog](https://github.com/gimli-rs/addr2line/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gimli-rs/addr2line/compare/0.12.1...0.12.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-21 18:08:44 +00:00
dependabot-preview[bot]
62eb66d87e build(deps): bump serde from 1.0.112 to 1.0.113
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.112 to 1.0.113.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.112...v1.0.113)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-20 13:36:11 +01:00
dependabot-preview[bot]
7e8c1ade12 build(deps): bump serde_derive from 1.0.112 to 1.0.113
Bumps [serde_derive](https://github.com/serde-rs/serde) from 1.0.112 to 1.0.113.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.112...v1.0.113)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-20 10:58:57 +01:00
dependabot-preview[bot]
025941ba73 build(deps): bump epoll from 4.1.0 to 4.2.0
Bumps [epoll](https://github.com/nathansizemore/epoll) from 4.1.0 to 4.2.0.
- [Release notes](https://github.com/nathansizemore/epoll/releases)
- [Commits](https://github.com/nathansizemore/epoll/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-19 06:02:13 +00:00
Rob Bradford
ec246b9702 build: Enable LTO for release build
This results in ~20% reduction of stripped binary size:

Default release build: 8.7M -> stripped: 5.3M
LTO release build: 5.9M -> stripped: 4.3M

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-17 21:44:21 +01:00
Rob Bradford
798f3f01a9 tests: Add integration tests for CPU topology
Add multiple integration tests with various different CPU topologies and
check that they work as expected.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-17 12:18:09 +02:00
Rob Bradford
a74c6fc14f vmm, arch: x86_64: Fill the CPUID leaves with the topology
There are two CPUID leaves for handling CPU topology, 0xb and 0x1f. The
difference between the two is that the 0x1f leaf (Extended Topology
Leaf) supports exposing multiple die packages.

Fixes: #1284

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-17 12:18:09 +02:00
Rob Bradford
e19079782d vmm, arch: x86_64: Set the APIC ID on the 0x1f CPUID leaf
The extended topology leaf (0x1f) also needs to have the APIC ID (which
is the KVM cpu ID) set. This mirrors the APIC ID set on the 0xb topology
leaf

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-17 12:18:09 +02:00
Rob Bradford
b81bc77390 vmm: cpu: Save CpusConfig into CpuManager
Rather than saving the individual parts into the CpuManager save the
full struct as it now also contains the topology data.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-17 12:18:09 +02:00
Rob Bradford
284891b5df main: Populate "--cpus" with appropriate syntax definition
This needed to be updated to include specifying the boot and maxmium
vCPUs as well as the newly added topology for those vCPUs.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-17 12:18:09 +02:00
Rob Bradford
4a0439a993 vmm: config: Extend CpusConfig to add the topology
This allows the user to optionally specify the desired CPU topology. All
parts of the topology must be specified and the product of all parts
must match the maximum vCPUs.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-17 12:18:09 +02:00
dependabot-preview[bot]
9099b067e1 build(deps): bump linux-loader from f7f2e89 to 2a62f21
Bumps [linux-loader](https://github.com/rust-vmm/linux-loader) from `f7f2e89` to `2a62f21`.
- [Release notes](https://github.com/rust-vmm/linux-loader/releases)
- [Commits](f7f2e890f7...2a62f21b44)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-17 09:34:08 +02:00
dependabot-preview[bot]
1d27416fd1 build(deps): bump unicode-normalization from 0.1.12 to 0.1.13
Bumps [unicode-normalization](https://github.com/unicode-rs/unicode-normalization) from 0.1.12 to 0.1.13.
- [Release notes](https://github.com/unicode-rs/unicode-normalization/releases)
- [Commits](https://github.com/unicode-rs/unicode-normalization/compare/v0.1.12...v0.1.13)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-16 22:49:54 +02:00
Stefano Garzarella
f756174b9f vsock: add muxer rxq regression test
This patch has been cherry-picked from the Firecracker tree. The
reference commit is 78ca0a942f32140465c67ea4b45d68c52c72d751.

Signed-off-by: Gabriel Ionescu <gbi@amazon.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
2020-06-16 22:02:06 +02:00
Stefano Garzarella
bb3cf7c30c vsock: add handshake regression test
This patch has been cherry-picked from the Firecracker tree. The
reference commit is 6dbe8e021a64ba3742081741a7538cdfd93a102e.

Signed-off-by: Gabriel Ionescu <gbi@amazon.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
2020-06-16 22:02:06 +02:00
Stefano Garzarella
6ab4e247e6 vsock: fixed TX buf flushing
This patch has been cherry-picked from the Firecracker tree. The
reference commit is 78819f35f63f5777a58e3e1e774b3270b32881ed.

The vsock TX buffer flush operation would report inconsistent results,
under specific circumstances.

The flush operation is performed in two steps, since it's dealing with a
ring buffer, an the data to be flushed may wrap around. If the first
step was successful, but the second one failed, the whole flush
operation would report an error, thus causing flow control accounting to
lose track of the bytes that were successfully written by the first
pass.

This commit changes the flush behavior to always report success when
some data has been written to the backing stream.

Signed-off-by: Dan Horobeanu <dhr@amazon.com>
Signed-off-by: Gabriel Ionescu <gbi@amazon.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
2020-06-16 22:02:06 +02:00
Stefano Garzarella
aca2baf458 vsock: fixed flow control regression
This patch has been cherry-picked from the Firecracker tree. The
reference commit is 2da612a9cdce85c91fb54ab22d950ec6ccc93b27.

Fixed a bug introduced by a271d08f0b1ba0ee82761cd49244b6a8017bcede,
whereby the flow control accouting would be off by a few bytes, for
host-initiated connections.

The connection ack message ("OK <port_num><CR>") was accounted for as
data sent by the guest, so its length was substracted from the total
amount of data the guest was allowed to send.

This commit changes the way this ack message is sent, so that it
bypasses flow control accouting.

Signed-off-by: Dan Horobeanu <dhr@amazon.com>
Signed-off-by: Gabriel Ionescu <gbi@amazon.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
2020-06-16 22:02:06 +02:00
Stefano Garzarella
3ce4bd5ec8 vsock: absorb spurious EPOLLOUT events
This patch has been cherry-picked from the Firecracker tree. The
reference commit is 109e631566350867dafa4b16c3919dfd1533eeea.

This commit changes the vsock connection state machine behavior to absorb
any EWOULDBLOCK errors recevied while handling an EPOLLOUT event. Previously,
this condition would lead to immediate connection termination.

Signed-off-by: Dan Horobeanu <dhr@amazon.com>
Signed-off-by: Gabriel Ionescu <gbi@amazon.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
2020-06-16 22:02:06 +02:00
Stefano Garzarella
0530b4e1ed vsock: absorb spurious EPOLLIN events
This patch has been cherry-picked from the Firecracker tree. The
reference commit is 660d18cf7fee5b38c3b1b17a5da6544b9025909d.

Apparently, epoll_wait sometimes yields false EPOLLIN events (i.e. events
follwing which read() would fail with EWOULDBLOCK). This would cause the
vsock connection state machine to terminate connections, since an error
was detected on the underlying Unix socket.

This commit changes the vsock connection state machine code to handle such
erroneous EPOLLIN events by absorbing EWOULDBLOCK read() errors.

Signed-off-by: Dan Horobeanu <dhr@amazon.com>
Signed-off-by: Gabriel Ionescu <gbi@amazon.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
2020-06-16 22:02:06 +02:00
Stefano Garzarella
a3f24e5fb9 vsock: flow control fix
This patch has been cherry-picked from the Firecracker tree. The
reference commit is 1cc8b8a678eb28b20f5843556bdb7fbb2dfa6284.

Fixed a logical error in the vsock flow control, that would cause credit
update packets to not be sent at the right time.

Signed-off-by: Dan Horobeanu <dhr@amazon.com>
Signed-off-by: Gabriel Ionescu <gbi@amazon.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
2020-06-16 22:02:06 +02:00
Stefano Garzarella
5fc52a5056 vsock: fixed rxq logic
This patch has been cherry-picked from the Firecracker tree. The
reference commit is d2475773557c82d2abad2fc8bdf69e7d01444109.

Fixed a vsock muxer issue that would cause a connection to be removed
from the RX queue, even though it still had pending RX data.

Signed-off-by: Dan Horobeanu <dhr@amazon.com>
Signed-off-by: Gabriel Ionescu <gbi@amazon.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
2020-06-16 22:02:06 +02:00
dependabot-preview[bot]
69dac2dbb5 build(deps): bump remain from 0.2.1 to 0.2.2
Bumps [remain](https://github.com/dtolnay/remain) from 0.2.1 to 0.2.2.
- [Release notes](https://github.com/dtolnay/remain/releases)
- [Commits](https://github.com/dtolnay/remain/compare/0.2.1...0.2.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-16 21:53:01 +02:00
dependabot-preview[bot]
19ab08f239 build(deps): bump itoa from 0.4.5 to 0.4.6
Bumps [itoa](https://github.com/dtolnay/itoa) from 0.4.5 to 0.4.6.
- [Release notes](https://github.com/dtolnay/itoa/releases)
- [Commits](https://github.com/dtolnay/itoa/compare/0.4.5...0.4.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-16 21:52:43 +02:00
dependabot-preview[bot]
a17aaec663 build(deps): bump adler32 from 1.0.4 to 1.1.0
Bumps [adler32](https://github.com/remram44/adler32-rs) from 1.0.4 to 1.1.0.
- [Release notes](https://github.com/remram44/adler32-rs/releases)
- [Commits](https://github.com/remram44/adler32-rs/compare/1.0.4...1.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-16 08:44:15 +02:00
dependabot-preview[bot]
8e5c816c2b build(deps): bump thiserror from 1.0.19 to 1.0.20
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.19 to 1.0.20.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.19...1.0.20)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-16 08:16:52 +02:00
Stefano Garzarella
096ffe08f2 vm-virtio: vsock: add is_empty method to VsockPacket
This patch adds `is_empty` method to VsockPacket to fix the
following clippy error:

error: item `vsock::packet::VsockPacket` has a public `len` method but no corresponding `is_empty` method
   --> vm-virtio/src/vsock/packet.rs:100:1
    |
100 | / impl VsockPacket {
101 | |     /// Create the packet wrapper from a TX virtq chain head.
102 | |     ///
103 | |     /// The chain head is expected to hold valid packet header data. A following packet buffer
...   |
334 | |     }
335 | | }
    | |_^
    |
    = note: `-D clippy::len-without-is-empty` implied by `-D warnings`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#len_without_is_empty

Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
2020-06-15 18:31:54 +01:00
Stefano Garzarella
b74a855446 vm-virtio: make VsockPacket public
This patch makes VsockPacket public to allow other crates
(e.g. vhost-user-vsock) to use it.

Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
2020-06-15 18:31:54 +01:00
dependabot-preview[bot]
8bcd0abbe5 build(deps): bump backtrace from 0.3.48 to 0.3.49
Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.48 to 0.3.49.
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.48...0.3.49)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-15 17:31:53 +01:00
Henry Wang
99e72be169 unit tests: Fix unit tests and docs for AArch64
Currently, not every feature of the cloud-hypervisor is enabled
on AArch64, which means that on AArch64 machines, the
`run_unit_tests.sh` needs to be tailored and some unit test cases
should be run on x86_64 only.

Also this commit fixes the typo and unifies `Arm64` and `AArch64`
in the AArch64 document.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2020-06-15 17:28:05 +01:00
Wei Liu
103cd61bd2 vmm: device_tree: make available remove function unconditionally
Its test case calls remove unconditionally. Instead of making the test
code call remove conditionally, removing the pci_support dependency
simplifies things -- that function is just a wrapper around HashMap's
remove function anyway.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-15 11:41:34 +02:00
dependabot-preview[bot]
66f7d20ee5 build(deps): bump linux-loader from 1af92d2 to f7f2e89
Bumps [linux-loader](https://github.com/rust-vmm/linux-loader) from `1af92d2` to `f7f2e89`.
- [Release notes](https://github.com/rust-vmm/linux-loader/releases)
- [Commits](1af92d21ad...f7f2e890f7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-15 08:56:24 +02:00
LiYa'nan
acc234088f vfio: fix for bug as below:
cloud-hypervisor: 763.978581807s: ERROR:pci/src/vfio.rs:651 -- failed to remove all guest memory regions from iommu table

when poweroff a vm with vfio device, clh will finally remove all guest memory region from iommu table
with the method unset_dma_map, not method setup_dma_map.

Signed-off-by: LiYa'nan <oliverliyn@gmail.com>
2020-06-15 08:51:13 +02:00
Rob Bradford
e080c6e5b0 Revert "build: Temporarily disable nightly builds"
This reverts commit 1a2b3c8f3e.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-15 06:43:27 +02:00
dependabot-preview[bot]
36f6d9da52 build(deps): bump serde from 1.0.111 to 1.0.112
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.111 to 1.0.112.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.111...v1.0.112)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-14 20:26:25 +01:00
dependabot-preview[bot]
9a99ebfd81 build(deps): bump serde_derive from 1.0.111 to 1.0.112
Bumps [serde_derive](https://github.com/serde-rs/serde) from 1.0.111 to 1.0.112.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.111...v1.0.112)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-14 20:26:01 +01:00
dependabot-preview[bot]
cb67372de2 build(deps): bump proc-macro-nested from 0.1.5 to 0.1.6
Bumps [proc-macro-nested](https://github.com/dtolnay/proc-macro-hack) from 0.1.5 to 0.1.6.
- [Release notes](https://github.com/dtolnay/proc-macro-hack/releases)
- [Commits](https://github.com/dtolnay/proc-macro-hack/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-14 13:02:33 +01:00
dependabot-preview[bot]
4171155540 build(deps): bump hermit-abi from 0.1.13 to 0.1.14
Bumps [hermit-abi](https://github.com/hermitcore/libhermit-rs) from 0.1.13 to 0.1.14.
- [Release notes](https://github.com/hermitcore/libhermit-rs/releases)
- [Commits](https://github.com/hermitcore/libhermit-rs/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-14 13:02:25 +01:00
dependabot-preview[bot]
2072145d71 build(deps): bump pin-project from 0.4.20 to 0.4.22
Bumps [pin-project](https://github.com/taiki-e/pin-project) from 0.4.20 to 0.4.22.
- [Release notes](https://github.com/taiki-e/pin-project/releases)
- [Changelog](https://github.com/taiki-e/pin-project/blob/master/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project/compare/v0.4.20...v0.4.22)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-14 13:02:14 +01:00
dependabot-preview[bot]
9eaa735ccb build(deps): bump remove_dir_all from 0.5.2 to 0.5.3
Bumps [remove_dir_all](https://github.com/XAMPPRocky/remove_dir_all) from 0.5.2 to 0.5.3.
- [Release notes](https://github.com/XAMPPRocky/remove_dir_all/releases)
- [Changelog](https://github.com/XAMPPRocky/remove_dir_all/blob/master/CHANGELOG.md)
- [Commits](https://github.com/XAMPPRocky/remove_dir_all/compare/v0.5.2...remove_dir_all@0.5.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-12 18:56:34 +01:00
Wei Liu
fb461c820f vmm: vm: enable test_vm test case
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-12 14:46:58 +01:00
Wei Liu
b99b5777bb vmm: vm: move some imports into test_vm
They are only needed there. Not moving them causes rustc to complain
about unused imports.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-12 14:46:58 +01:00
Sebastien Boeuf
4f311b56eb ci: Extend integration tests for checking PCI hotplug response
Upon PCI hotplug, the VMM now returns some information about the device
name and the associated b/d/f. This patch extends the integration tests
so that we validate the response is the one that is expected.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-12 13:37:18 +01:00
Sebastien Boeuf
b62d5d22ff vmm: openapi: Update the OpenAPI definition
Now that PCI device hotplug returns a response, the OpenAPI definition
must reflect it, describing what is expected to be received.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-12 13:37:18 +01:00
Sebastien Boeuf
4fe7347fb9 vmm: Manually implement Serialize for PciDeviceInfo
In order to provide a more comprehensive b/d/f to the user, the
serialization of PciDeviceInfo is implemented manually to control the
formatting.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-12 13:37:18 +01:00
Sebastien Boeuf
83cd9969df vmm: Enable HTTP response for PCI device hotplug
This patch completes the series by connecting the dots between the HTTP
frontend and the device manager backend.

Any request to hotplug a VFIO, disk, fs, pmem, net, or vsock device will
now return a response including the device name and the place of the
device in the PCI topology.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-12 13:37:18 +01:00
Sebastien Boeuf
3316348d4c vmm: vm: Carry information from hotplugged PCI device
Pass from the device manager to the calling code the information about
the PCI device that has just been hotplugged.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-12 13:37:18 +01:00
Sebastien Boeuf
f08e9b6a73 vmm: device_manager: Return PciDeviceInfo from a hotplugged device
In order to provide the device name and PCI b/d/f associated with a
freshly hotplugged device, the hotplugging functions from the device
manager return a new structure called PciDeviceInfo.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-12 13:37:18 +01:00
Sebastien Boeuf
0bc2b08d3a vmm: api: Return an optional response from vm_action()
Any action that relies on vm_action() can now return a response body.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-12 13:37:18 +01:00
Sebastien Boeuf
038180269e vmm: api: Allow HTTP PUT request to return a response
Adding the codepath to return a response from a PUT request.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2020-06-12 13:37:18 +01:00
Rob Bradford
1a2b3c8f3e build: Temporarily disable nightly builds
Rust nightly builds are currently failing due to a crate outside of
our control not meeting the latest cargo requirements.

See XAMPPRocky/remove_dir_all#19

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2020-06-12 10:07:00 +01:00
Wei Liu
5ebd02a572 vmm: vm: fix test_vm test case
We should break out from the loop after getting the HLT exit, otherwise
the VM hangs forever.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2020-06-12 08:38:07 +02:00
261 changed files with 44011 additions and 25467 deletions

15
.github/workflows/audit.yaml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: Cloud Hypervisor Dependency Audit
on:
pull_request:
paths:
- '**/Cargo.toml'
- '**/Cargo.lock'
jobs:
security_audit:
name: Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions-rs/audit-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -7,6 +7,7 @@ jobs:
name: Build
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
rust:
- stable
@@ -18,6 +19,9 @@ jobs:
steps:
- name: Code checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Install Rust toolchain (${{ matrix.rust }})
uses: actions-rs/toolchain@v1
with:
@@ -25,5 +29,16 @@ jobs:
target: ${{ matrix.target }}
override: true
- name: Build
run: cargo build --release --target=${{ matrix.target }}
- name: Debug Check (default features)
run: |
git rev-list origin/master..$GITHUB_SHA | xargs -t -I % sh -c 'git checkout %; cargo check --all --target=${{ matrix.target }}'
git checkout $GITHUB_SHA
- name: Build (acpi,kvm)
run: cargo rustc --bin cloud-hypervisor --no-default-features --features "acpi,kvm" -- -D warnings
- name: Build (kvm)
run: cargo rustc --bin cloud-hypervisor --no-default-features --features "kvm" -- -D warnings
- name: Release Build (default features)
run: cargo build --all --release --target=${{ matrix.target }}

36
.github/workflows/docker-image.yaml vendored Normal file
View File

@@ -0,0 +1,36 @@
name: Cloud-Hypervisor's Docker image update
on:
push:
branches: master
paths: resources/Dockerfile
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: Code checkout
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v2
with:
file: ./resources/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: cloudhypervisor/dev:latest
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}

27
.github/workflows/fuzz-build.yaml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Cloud Hypervisor Cargo Fuzz Build
on: [pull_request, create]
jobs:
build:
if: github.event_name == 'pull_request'
name: Cargo Fuzz Build
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- nightly
target:
- x86_64-unknown-linux-gnu
steps:
- name: Code checkout
uses: actions/checkout@v2
- name: Install Rust toolchain (${{ matrix.rust }})
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
override: true
- name: Install Cargo fuzz
run: cargo install -f cargo-fuzz
- name: Cargo Fuzz Build
run: cargo fuzz build

View File

@@ -1,10 +1,10 @@
name: Cloud Hypervisor Cross Build
name: Cloud Hypervisor Quality Checks
on: [pull_request, create]
jobs:
build:
if: github.event_name == 'pull_request'
name: Build
name: Quality (clippy, rustfmt)
runs-on: ubuntu-latest
strategy:
matrix:
@@ -12,7 +12,6 @@ jobs:
- stable
target:
- aarch64-unknown-linux-gnu
- aarch64-unknown-linux-musl
steps:
- name: Code checkout
uses: actions/checkout@v2
@@ -22,13 +21,14 @@ jobs:
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
override: true
components: rustfmt, clippy
- name: Install arm64 libfdt
run: wget http://ftp.us.debian.org/debian/pool/main/d/device-tree-compiler/libfdt-dev_1.6.0-1_arm64.deb && dpkg-deb -xv libfdt-dev_1.6.0-1_arm64.deb ./tlibfdtdev && sudo mkdir /tmmmp && mkdir target && mkdir target/debug && mkdir target/debug/deps && sudo cp ./tlibfdtdev/usr/lib/aarch64-linux-gnu/libfdt.a target/debug/deps/libfdt.a && echo "libfdt installed"
- name: Disable "with-serde" in kvm-bindings
run: sed -i 's/"with-serde",\ //g' vmm/Cargo.toml
- name: Build
run: wget http://ftp.us.debian.org/debian/pool/main/d/device-tree-compiler/libfdt-dev_1.6.0-1_arm64.deb && dpkg-deb -xv libfdt-dev_1.6.0-1_arm64.deb ./tlibfdtdev && mkdir -p target/debug/deps && sudo cp ./tlibfdtdev/usr/lib/aarch64-linux-gnu/libfdt.a target/debug/deps/libfdt.a && echo "libfdt installed"
- name: Formatting (rustfmt)
run: cargo fmt -- --check
- name: Clippy (kvm)
uses: actions-rs/cargo@v1
with:
use-cross: true
command: build
args: --target=${{ matrix.target }} --no-default-features --features "mmio"
command: clippy
args: --target=${{ matrix.target }} --no-default-features --features "kvm" -- -D warnings

51
.github/workflows/quality.yaml vendored Normal file
View File

@@ -0,0 +1,51 @@
name: Cloud Hypervisor Quality Checks
on: [pull_request, create]
jobs:
build:
if: github.event_name == 'pull_request'
name: Quality (clippy, rustfmt)
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
target:
- x86_64-unknown-linux-gnu
steps:
- name: Code checkout
uses: actions/checkout@v2
- name: Install Rust toolchain (${{ matrix.rust }})
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
override: true
components: rustfmt, clippy
- name: Formatting (rustfmt)
run: cargo fmt -- --check
- name: Clippy (all features,kvm)
run: cargo clippy --all --all-targets --no-default-features --tests --features "common,kvm" -- -D warnings
- name: Clippy (all features,mshv)
run: cargo clippy --all --all-targets --no-default-features --tests --features "common,mshv" -- -D warnings
- name: Clippy (acpi,kvm)
run: cargo clippy --all --all-targets --no-default-features --tests --features "acpi,kvm" -- -D warnings
- name: Clippy (acpi,kvm,tdx)
run: cargo clippy --all --all-targets --no-default-features --tests --features "acpi,kvm,tdx" -- -D warnings
- name: Clippy (kvm)
run: cargo clippy --all --all-targets --no-default-features --tests --features "kvm" -- -D warnings
- name: Clippy (acpi,mshv)
run: cargo clippy --all --all-targets --no-default-features --tests --features "acpi,mshv" -- -D warnings
- name: Clippy (mshv)
run: cargo clippy --all --all-targets --no-default-features --tests --features "mshv" -- -D warnings
- name: Clippy (integration tests)
run: cargo clippy --all --all-targets --tests --features "integration_tests" -- -D warnings

View File

@@ -20,9 +20,9 @@ jobs:
toolchain: stable
target: x86_64-unknown-linux-musl
- name: Build
run: cargo build --release --target=x86_64-unknown-linux-gnu
run: cargo build --all --release --target=x86_64-unknown-linux-gnu
- name: Static Build
run: cargo build --release --target=x86_64-unknown-linux-musl
run: cargo build --all --release --target=x86_64-unknown-linux-musl
- name: Strip cloud-hypervisor binaries
run: strip target/*/release/cloud-hypervisor
- name: Create Release

View File

@@ -88,5 +88,5 @@ Fixes #88
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
```
Then, after the correspoding PR is merged, Github will automatically close that issue when parsing the
Then, after the corresponding PR is merged, Github will automatically close that issue when parsing the
[commit message](https://help.github.com/articles/closing-issues-via-commit-messages/).

1012
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,74 +1,89 @@
[package]
name = "cloud-hypervisor"
version = "0.8.0"
version = "0.14.1"
authors = ["The Cloud Hypervisor Authors"]
edition = "2018"
default-run = "cloud-hypervisor"
build = "build.rs"
license = "LICENSE-APACHE & LICENSE-BSD-3-Clause"
description = "Open source Virtual Machine Monitor (VMM) that runs on top of KVM"
homepage = "https://github.com/cloud-hypervisor/cloud-hypervisor"
[profile.release]
lto = true
[dependencies]
arc-swap = ">=0.4.4"
clap = { version = "2.33.1", features=["wrap_help"] }
epoll = ">=4.0.1"
futures = { version = "0.3.5", features = ["thread-pool"] }
lazy_static = "1.4.0"
libc = "0.2.71"
log = { version = "0.4.8", features = ["std"] }
seccomp = { git = "https://github.com/firecracker-microvm/firecracker", tag = "v0.21.1" }
serde_json = ">=1.0.9"
vhost_user_backend = { path = "vhost_user_backend"}
vhost_user_block = { path = "vhost_user_block"}
vhost_user_fs = { path = "vhost_user_fs"}
vhost_user_net = { path = "vhost_user_net"}
virtio-bindings = { version = "0.1", features = ["virtio-v5_0_0"]}
anyhow = "1.0.39"
api_client = { path = "api_client" }
clap = { version = "2.33.3", features = ["wrap_help"] }
epoll = "4.3.1"
event_monitor = { path = "event_monitor" }
hypervisor = { path = "hypervisor" }
libc = "0.2.91"
log = { version = "0.4.14", features = ["std"] }
option_parser = { path = "option_parser" }
seccomp = { git = "https://github.com/firecracker-microvm/firecracker", tag = "v0.22.0" }
serde_json = "1.0.64"
signal-hook = "0.3.7"
thiserror = "1.0.24"
vmm = { path = "vmm" }
vm-device = { path = "vm-device" }
vm-memory = "0.2.1"
vmm-sys-util = "0.6.1"
vm-virtio = { path = "vm-virtio" }
vhost_rs = { git = "https://github.com/cloud-hypervisor/vhost", branch = "dragonball", package = "vhost", features = ["vhost-user-slave"] }
vmm-sys-util = "0.8.0"
vm-memory = "0.5.0"
[build-dependencies]
clap = { version = "2.33.3", features = ["wrap_help"] }
# List of patched crates
[patch.crates-io]
vm-memory = { git = "https://github.com/cloud-hypervisor/vm-memory", branch = "ch" }
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.4.0", features = ["with-serde", "fam-wrappers"] }
[dev-dependencies]
ssh2 = "0.8.1"
dirs = "2.0.2"
credibility = "0.1.3"
tempdir= "0.3.7"
dirs = "3.0.1"
lazy_static= "1.4.0"
tempfile = "3.1.0"
serde_json = ">=1.0.9"
net_util = { path = "net_util" }
serde_json = "1.0.64"
test_infra = { path = "test_infra" }
wait-timeout = "0.2.0"
[features]
default = ["acpi", "pci", "cmos"]
default = ["acpi", "cmos", "io_uring", "kvm"]
# Common features for all hypervisors
common = ["acpi", "cmos", "fwdebug", "io_uring"]
acpi = ["vmm/acpi"]
pci = ["vmm/pci_support"]
mmio = ["vmm/mmio_support"]
cmos = ["vmm/cmos"]
fwdebug = ["vmm/fwdebug"]
kvm = ["vmm/kvm"]
mshv = ["vmm/mshv"]
io_uring = ["vmm/io_uring"]
tdx = ["vmm/tdx"]
# Integration tests require a special environment to run in
integration_tests = []
[workspace]
members = [
"acpi_tables",
"api_client",
"arch",
"arch_gen",
"block_util",
"devices",
"qcow",
"event_monitor",
"hypervisor",
"net_gen",
"net_util",
"option_parser",
"pci",
"qcow",
"vhost_user_backend",
"vhost_user_block",
"vhost_user_net",
"virtio-devices",
"vmm",
"vm-virtio",
"vm-allocator",
"vm-device",
"vm-migration",
"vhost_user_block",
"vhost_user_backend",
"vhost_user_fs",
"vhost_user_net",
"net_util",
"acpi_tables",
"arch_gen",
"net_gen",
"vm-allocator",
"vm-virtio"
]
exclude = ["test_infra"]

176
Jenkinsfile vendored
View File

@@ -22,33 +22,37 @@ pipeline{
}
}
stage ('Build') {
failFast true
parallel {
stage ('Master build') {
agent { node { label 'master' } }
parallel {
stage ('Worker build') {
agent { node { label 'groovy' } }
stages {
stage ('Checkout') {
steps {
checkout scm
}
}
stage ('Run Cargo tests') {
steps {
sh "scripts/dev_cli.sh tests --cargo"
}
}
stage ('Run OpenAPI tests') {
steps {
sh "scripts/run_openapi_tests.sh"
}
}
stage ('Run unit tests') {
steps {
sh "scripts/dev_cli.sh tests --unit"
}
}
stage ('Run integration tests') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh "scripts/dev_cli.sh tests --integration"
}
}
}
}
stage ('Worker build') {
agent { node { label 'bionic' } }
options {
timeout(time: 1, unit: 'HOURS')
}
}
stage ('AArch64 worker build') {
agent { node { label 'bionic-arm64' } }
stages {
stage ('Checkout') {
steps {
@@ -61,17 +65,23 @@ pipeline{
}
}
stage ('Run integration tests') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh "scripts/dev_cli.sh tests --integration"
}
}
}
post {
always {
sh "sudo chown -R jenkins.jenkins ${WORKSPACE}"
deleteDir()
}
}
}
stage ('Worker build (musl)') {
agent { node { label 'bionic' } }
options {
timeout(time: 1, unit: 'HOURS')
}
agent { node { label 'groovy' } }
stages {
stage ('Checkout') {
steps {
@@ -84,12 +94,138 @@ pipeline{
}
}
stage ('Run integration tests for musl') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh "scripts/dev_cli.sh tests --integration --libc musl"
}
}
}
}
stage ('Worker build SGX') {
agent { node { label 'bionic-sgx' } }
when { branch 'master' }
stages {
stage ('Checkout') {
steps {
checkout scm
}
}
stage ('Run SGX integration tests') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh "scripts/dev_cli.sh tests --integration-sgx"
}
}
stage ('Run SGX integration tests for musl') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh "scripts/dev_cli.sh tests --integration-sgx --libc musl"
}
}
}
post {
always {
sh "sudo chown -R jenkins.jenkins ${WORKSPACE}"
deleteDir()
}
}
}
stage ('Worker build VFIO') {
agent { node { label 'bionic-vfio' } }
when { branch 'master' }
stages {
stage ('Checkout') {
steps {
checkout scm
}
}
stage ('Run VFIO integration tests') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh "scripts/dev_cli.sh tests --integration-vfio"
}
}
stage ('Run VFIO integration tests for musl') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh "scripts/dev_cli.sh tests --integration-vfio --libc musl"
}
}
}
post {
always {
sh "sudo chown -R jenkins.jenkins ${WORKSPACE}"
deleteDir()
}
}
}
stage ('Worker build - Windows guest') {
agent { node { label 'groovy-win' } }
stages {
stage ('Checkout') {
steps {
checkout scm
}
}
stage ('Download assets') {
steps {
sh "mkdir ${env.HOME}/workloads"
azureDownload(storageCredentialId: 'ch-image-store',
containerName: 'private-images',
includeFilesPattern: 'OVMF-4b47d0c6c8.fd',
downloadType: 'container',
downloadDirLoc: "${env.HOME}/workloads")
azureDownload(storageCredentialId: 'ch-image-store',
containerName: 'private-images',
includeFilesPattern: 'windows-server-2019.raw',
downloadType: 'container',
downloadDirLoc: "${env.HOME}/workloads")
}
}
stage ('Run Windows guest integration tests') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh "scripts/dev_cli.sh tests --integration-windows"
}
}
stage ('Run Windows guest integration tests for musl') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh "scripts/dev_cli.sh tests --integration-windows --libc musl"
}
}
}
}
}
}
}
post {
regression {
script {
if (env.BRANCH_NAME == 'master') {
slackSend (color: '#ff0000', message: '"master" branch build is now failing')
}
}
}
fixed {
script {
if (env.BRANCH_NAME == 'master') {
slackSend (color: '#00ff00', message: '"master" branch build is now fixed')
}
}
}
}
@@ -108,4 +244,4 @@ def cancelPreviousBuilds() {
build.doStop()
}
}
}
}

193
README.md
View File

@@ -1,35 +1,34 @@
[![Build Status](https://travis-ci.com/cloud-hypervisor/cloud-hypervisor.svg?branch=master)](https://travis-ci.com/cloud-hypervisor/cloud-hypervisor)
1. [What is Cloud Hypervisor?](#1-what-is-cloud-hypervisor)
* [Requirements](#requirements)
+ [High Level](#high-level)
+ [Architectures](#architectures)
+ [Guest OS](#guest-os)
2. [Getting Started](#2-getting-started)
* [Clone and build](#clone-and-build)
* [Run](#run)
+ [Cloud image](#cloud-image)
+ [Custom kernel and disk image](#custom-kernel-and-disk-image)
- [Building your kernel](#building-your-kernel)
- [Disk image](#disk-image)
- [Booting the guest VM](#booting-the-guest-vm)
3. [Status](#2-status)
* [Device Model](#device-model)
* [TODO](#todo)
4. [rust-vmm dependency](#4-rust-vmm-dependency)
* [Firecracker and crosvm](#firecracker-and-crosvm)
5. [Community](#5-community)
* [Join us](#join-us)
6. [Security](#6-security)
- [1. What is Cloud Hypervisor?](#1-what-is-cloud-hypervisor)
- [Objectives](#objectives)
- [High Level](#high-level)
- [Architectures](#architectures)
- [Guest OS](#guest-os)
- [2. Getting Started](#2-getting-started)
- [Clone and build](#clone-and-build)
- [Containerized builds and tests](#containerized-builds-and-tests)
- [Run](#run)
- [Cloud image](#cloud-image)
- [Custom kernel and disk image](#custom-kernel-and-disk-image)
- [Building your kernel](#building-your-kernel)
- [Disk image](#disk-image)
- [Booting the guest VM](#booting-the-guest-vm)
- [3. Status](#3-status)
- [Hot Plug](#hot-plug)
- [Device Model](#device-model)
- [TODO](#todo)
- [4. `rust-vmm` project dependency](#4-rust-vmm-project-dependency)
- [Firecracker and crosvm](#firecracker-and-crosvm)
- [5. Community](#5-community)
- [Contribute](#contribute)
- [Join us](#join-us)
# 1. What is Cloud Hypervisor?
**This project is an experiment and should not be used with production workloads.**
Cloud Hypervisor is an open source Virtual Machine Monitor (VMM) that runs on top of [KVM](https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt).
The project focuses on exclusively running modern, cloud workloads, on top of a limited set of hardware architectures and platforms.
Cloud workloads refers to those that are usually run by customers inside a cloud provider. For our purposes this means modern
Linux* distributions with most I/O handled by paravirtualised devices (i.e. virtio), no requirement for legacy devices and recent CPUs and KVM.
Cloud workloads refers to those that are usually run by customers inside a cloud provider. For our purposes this means modern operating systems with most I/O handled by paravirtualised devices (i.e. virtio), no requirement for legacy devices, and 64-bit CPUs.
Cloud Hypervisor is implemented in [Rust](https://www.rust-lang.org/) and is based on the [rust-vmm](https://github.com/rust-vmm) crates.
@@ -37,27 +36,24 @@ Cloud Hypervisor is implemented in [Rust](https://www.rust-lang.org/) and is bas
### High Level
* KVM and KVM only based
* Minimal emulation
* Low latency
* Low memory footprint
* Low complexity
* High performance
* Small attack surface
* 64-bit support only
* Build time configurable CPU, memory, PCI and NVDIMM hotplug
* Machine to machine migration
- KVM based
- Minimal emulation
- Low latency
- Low memory footprint
- Low complexity
- High performance
- Small attack surface
- 64-bit support only
- CPU, memory, PCI hotplug
- Machine to machine migration
### Architectures
`cloud-hypervisor` only supports the `x86-64` CPU architecture for now.
We're planning to add support for the `AArch64` architecture in the future.
Cloud Hypervisor supports the `x86-64` and `AArch64` architectures. There are some small differences in functionality between the two architectures (see [#1125](https://github.com/cloud-hypervisor/cloud-hypervisor/issues/1125)).
### Guest OS
* `64-bit Linux`
Support for *modern* 64-bit Windows guest is being evaluated.
Cloud Hypervisor supports `64-bit Linux` with support for _modern_ 64-bit Windows guests currently under development.
# 2. Getting Started
@@ -68,6 +64,23 @@ $ export CLOUDH=$HOME/cloud-hypervisor
$ mkdir $CLOUDH
```
## Install prerequisites
You need to install some prerequisite packages in order to build and test Cloud Hypervisor.
Here, all the steps are based on Ubuntu, for other Linux distributions please replace the
package manager and package name.
```shell
# Install git
$ sudo apt install git
# Install rust tool chain
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Install build-essential
$ sudo apt install build-essential
# If you want to build statically linked binary please add musl target
$ rustup target add x86_64-unknown-linux-musl
```
## Clone and build
First you need to clone and build the cloud-hypervisor repo:
@@ -81,6 +94,8 @@ $ cargo build --release
# We need to give the cloud-hypervisor binary the NET_ADMIN capabilities for it to set TAP interfaces up on the host.
$ sudo setcap cap_net_admin+ep ./target/release/cloud-hypervisor
# If you want to build statically linked binary
$ cargo build --release --target=x86_64-unknown-linux-musl --all
$ popd
```
@@ -120,20 +135,20 @@ You can run a guest VM by either using an existing cloud image or booting into y
### Cloud image
`cloud-hypervisor` supports booting disk images containing all needed
components to run cloud workloads, a.k.a. cloud images. To do that we rely on
Cloud Hypervisor supports booting disk images containing all needed
components to run cloud workloads, a.k.a. cloud images. To do that we rely on
the [Rust Hypervisor
Firmware](https://github.com/cloud-hypervisor/rust-hypervisor-firmware) project to provide
an ELF
formatted KVM firmware for `cloud-hypervisor` to directly boot into.
We need to get the latest `rust-hypervisor-firmware` release and also a working cloud image. Here we will use a Clear Linux image:
We need to get the latest `rust-hypervisor-firmware` release and also a working cloud image. Here we will use a Ubuntu image:
```shell
$ pushd $CLOUDH
$ wget https://download.clearlinux.org/releases/31890/clear/clear-31890-kvm.img.xz
$ unxz clear-31890-kvm.img.xz
$ wget https://github.com/cloud-hypervisor/rust-hypervisor-firmware/releases/download/0.2.6/hypervisor-fw
$ wget https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img
$ qemu-img convert -p -f qcow2 -O raw focal-server-cloudimg-amd64.img focal-server-cloudimg-amd64.raw
$ wget https://github.com/cloud-hypervisor/rust-hypervisor-firmware/releases/download/0.3.0/hypervisor-fw
$ popd
```
@@ -142,7 +157,7 @@ $ pushd $CLOUDH
$ sudo setcap cap_net_admin+ep ./cloud-hypervisor/target/release/cloud-hypervisor
$ ./cloud-hypervisor/target/release/cloud-hypervisor \
--kernel ./hypervisor-fw \
--disk path=clear-31890-kvm.img \
--disk path=focal-server-cloudimg-amd64.raw \
--cpus boot=4 \
--memory size=1024M \
--net "tap=,mac=,ip=,mask=" \
@@ -156,8 +171,7 @@ Multiple arguments can be given to the `--disk` parameter.
#### Building your kernel
`cloud-hypervisor` also supports direct kernel boot into a `vmlinux` ELF kernel
image. In order to support virtio-fs and virtio-iommu we have our own development branch. You are of course able to use your own kernel but these instructions will continue with the version that we develop and test against.
Cloud Hypervisor also supports direct kernel boot into a `vmlinux` ELF kernel or `bzImage`. In order to support virtio-fs and virtio-iommu we have our own development branch. You are of course able to use your own kernel but these instructions will continue with the version that we develop and test against.
To build the kernel:
@@ -169,7 +183,7 @@ $ git clone --depth 1 https://github.com/cloud-hypervisor/linux.git -b virtio-fs
$ pushd linux-cloud-hypervisor
# Use the cloud-hypervisor kernel config to build your kernel
$ cp $CLOUDH/cloud-hypervisor/resources/linux-config .config
$ cp $CLOUDH/cloud-hypervisor/resources/linux-config-x86_64 .config
$ make bzImage -j `nproc`
$ popd
```
@@ -178,18 +192,18 @@ The `vmlinux` kernel image will then be located at `linux-cloud-hypervisor/arch/
#### Disk image
For the disk image, we will use a Clear Linux cloud image that contains a root partition:
For the disk image, we will use a Ubuntu cloud image that contains a root partition:
```shell
$ pushd $CLOUDH
$ wget https://download.clearlinux.org/releases/31890/clear/clear-31890-kvm.img.xz
$ unxz clear-31890-kvm.img.xz
$ wget https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img
$ qemu-img convert -p -f qcow2 -O raw focal-server-cloudimg-amd64.img focal-server-cloudimg-amd64.raw
$ popd
```
#### Booting the guest VM
Now we can directly boot into our custom kernel and make it use the Clear Linux root partition.
Now we can directly boot into our custom kernel and make it use the Ubuntu root partition.
If we want to have 4 vCPUs and 512 MBytes of memory:
```shell
@@ -197,8 +211,8 @@ $ pushd $CLOUDH
$ sudo setcap cap_net_admin+ep ./cloud-hypervisor/target/release/cloud-hypervisor
$ ./cloud-hypervisor/target/release/cloud-hypervisor \
--kernel ./linux-cloud-hypervisor/arch/x86/boot/compressed/vmlinux.bin \
--disk path=clear-31890-kvm.img \
--cmdline "console=hvc0 reboot=k panic=1 nomodules i8042.noaux i8042.nomux i8042.nopnp i8042.dumbkbd root=/dev/vda3" \
--disk path=focal-server-cloudimg-amd64.raw \
--cmdline "console=hvc0 root=/dev/vda1 rw" \
--cpus boot=4 \
--memory size=1024M \
--net "tap=,mac=,ip=,mask=" \
@@ -217,8 +231,8 @@ $ ./cloud-hypervisor/target/release/cloud-hypervisor \
--kernel ./linux-cloud-hypervisor/arch/x86/boot/compressed/vmlinux.bin \
--console off \
--serial tty \
--disk path=clear-31890-kvm.img \
--cmdline "console=ttyS0 reboot=k panic=1 nomodules i8042.noaux i8042.nomux i8042.nopnp i8042.dumbkbd root=/dev/vda3" \
--disk path=focal-server-cloudimg-amd64.raw \
--cmdline "console=ttyS0 root=/dev/vda1 rw" \
--cpus boot=4 \
--memory size=1024M \
--net "tap=,mac=,ip=,mask=" \
@@ -227,52 +241,52 @@ $ ./cloud-hypervisor/target/release/cloud-hypervisor \
# 3. Status
`cloud-hypervisor` is in a very early, pre-alpha stage. Use at your own risk!
Cloud Hypervisor is under active development. No API or feature stability is guaranteed.
As of 2020-04-23, the following cloud images are supported:
* [Clear Linux](https://download.clearlinux.org/current/) (cloudguest and kvm)
* [Ubuntu Bionic](https://cloud-images.ubuntu.com/bionic/current/) (cloudimg)
* [Ubuntu Focal](https://cloud-images.ubuntu.com/focal/current/) (cloudimg)
As of 2020-07-02, the following cloud images are supported:
Direct kernel boot to userspace should work with most rootfs.
- [Ubuntu Bionic](https://cloud-images.ubuntu.com/bionic/current/) (cloudimg)
- [Ubuntu Focal](https://cloud-images.ubuntu.com/focal/current/) (cloudimg)
Direct kernel boot to userspace should work with a rootfs from most distributions.
## Hot Plug
This [document](https://github.com/cloud-hypervisor/cloud-hypervisor/blob/master/docs/hotplug.md) details how to add devices to
a running VM. Currently only CPU hot plug is supported.
Cloud Hypervisor supports hotplug of CPUs, passthrough devices (VFIO), `virtio-{net,block,pmem,fs,vsock}` and memory resizing. This [document](https://github.com/cloud-hypervisor/cloud-hypervisor/blob/master/docs/hotplug.md) details how to add devices to
a running VM.
## Device Model
Follow this [documentation](https://github.com/cloud-hypervisor/cloud-hypervisor/blob/master/docs/device_model.md).
Details of the device model can be found in this [documentation](https://github.com/cloud-hypervisor/cloud-hypervisor/blob/master/docs/device_model.md).
## TODO
We are not tracking the `cloud-hypervisor` TODO list from a specific git tracked file but through
We are not tracking the Cloud Hypervisor TODO list from a specific git tracked file but through
[github issues](https://github.com/cloud-hypervisor/cloud-hypervisor/issues/new) instead.
# 4. `rust-vmm` project dependency
In order to satisfy the design goal of having a high-performance, security-focused hypervisor the decision
was made to use the [Rust](https://www.rust-lang.org/) programming language.
The language's strong focus on memory and thread safety makes it an ideal candidate for implementing VMMs
The language's strong focus on memory and thread safety makes it an ideal candidate for implementing VMMs.
Instead of implementing the VMM components from scratch, `cloud-hypervisor` is importing the [rust-vmm](https://github.com/rust-vmm)
Instead of implementing the VMM components from scratch, Cloud Hypervisor is importing the [rust-vmm](https://github.com/rust-vmm)
crates, and sharing code and architecture together with other VMMs like e.g. Amazon's [Firecracker](https://firecracker-microvm.github.io/)
and Google's [crosvm](https://chromium.googlesource.com/chromiumos/platform/crosvm/).
`cloud-hypervisor` embraces the rust-vmm project goals, which is to be able to share and re-use
as many virtualization crates as possible. As such, the `cloud-hypervisor` relationship with the rust-vmm
Cloud Hypervisor embraces the rust-vmm project goals, which is to be able to share and re-use
as many virtualization crates as possible. As such, the Cloud Hypervisor relationship with the rust-vmm
project is twofold:
1. It will use as much of the rust-vmm code as possible. Any new rust-vmm crate that's relevant to the project
goals will be integrated as soon as possible.
2. As it is likely that the rust-vmm project will lack some of the features that `cloud-hypervisor` needs (e.g. ACPI,
VFIO, vhost-user, etc), we will be using the `cloud-hypervisor` VMM to implement and test them, and contribute them
2. As it is likely that the rust-vmm project will lack some of the features that Cloud Hypervisor needs (e.g. ACPI,
VFIO, vhost-user, etc), we will be using the Cloud Hypervisor VMM to implement and test them, and contribute them
back to the rust-vmm project.
## Firecracker and crosvm
A large part of the `cloud-hypervisor` code is based on either the Firecracker or the crosvm projects implementations.
A large part of the Cloud Hypervisor code is based on either the Firecracker or the crosvm projects implementations.
Both of these are VMMs written in Rust with a focus on safety and security, like Cloud Hypervisor.
However we want to emphasize that the Cloud Hypervisor project is neither a fork nor a reimplementation of any of those
@@ -287,6 +301,11 @@ crates as possible.
# 5. Community
The Cloud Hypervisor project follows the governance, and community guidelines described in
the [Community](https://github.com/cloud-hypervisor/community) repository.
## Contribute
We are working on building a global, diverse and collaborative community around the Cloud Hypervisor project.
Anyone who is interested in [contributing](CONTRIBUTING.md) to the project is welcome to participate.
@@ -298,27 +317,3 @@ etc, are all equal and welcome means of contribution. See the [CONTRIBUTING](CON
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/).
# 6. Security
**Reporting a Potential Security Vulnerability**: If you have discovered
potential security vulnerability in this project, please send an e-mail to
secure@intel.com. For issues related to Intel Products, please visit
https://security-center.intel.com.
It is important to include the following details:
- The projects and versions affected
- Detailed description of the vulnerability
- Information on known exploits
Vulnerability information is extremely sensitive. Please encrypt all security
vulnerability reports using our *PGP key*
A member of the Intel Product Security Team will review your e-mail and
contact you to to collaborate on resolving the issue. For more information on
how Intel works to resolve security issues, see: *Vulnerability Handling
Guidelines*
PGP Key: https://www.intel.com/content/www/us/en/security-center/pgp-public-key.html
Vulnerability Handling Guidelines: https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html

View File

@@ -5,5 +5,5 @@ authors = ["The Cloud Hypervisor Authors"]
edition = "2018"
[dependencies]
vm-memory = "0.2.1"
vm-memory = "0.5.0"

View File

@@ -95,8 +95,7 @@ pub type Byte = u8;
impl Aml for Byte {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0x0a); /* BytePrefix */
let mut bytes = vec![0x0a]; /* BytePrefix */
bytes.push(*self);
bytes
}
@@ -106,8 +105,7 @@ pub type Word = u16;
impl Aml for Word {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0x0bu8); /* WordPrefix */
let mut bytes = vec![0x0bu8]; /* WordPrefix */
bytes.append(&mut self.to_le_bytes().to_vec());
bytes
}
@@ -117,8 +115,7 @@ pub type DWord = u32;
impl Aml for DWord {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0x0c); /* DWordPrefix */
let mut bytes = vec![0x0c]; /* DWordPrefix */
bytes.append(&mut self.to_le_bytes().to_vec());
bytes
}
@@ -128,8 +125,7 @@ pub type QWord = u64;
impl Aml for QWord {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0x0e); /* QWordPrefix */
let mut bytes = vec![0x0e]; /* QWordPrefix */
bytes.append(&mut self.to_le_bytes().to_vec());
bytes
}
@@ -147,8 +143,7 @@ impl Aml for Name {
impl Name {
pub fn new(path: Path, inner: &dyn Aml) -> Self {
let mut bytes = Vec::new();
bytes.push(0x08); /* NameOp */
let mut bytes = vec![0x08]; /* NameOp */
bytes.append(&mut path.to_aml_bytes());
bytes.append(&mut inner.to_aml_bytes());
Name { bytes }
@@ -161,8 +156,7 @@ pub struct Package<'a> {
impl<'a> Aml for Package<'a> {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(self.children.len() as u8);
let mut bytes = vec![self.children.len() as u8];
for child in &self.children {
bytes.append(&mut child.to_aml_bytes());
}
@@ -239,11 +233,11 @@ fn create_pkg_length(data: &[u8], include_self: bool) -> Vec<u8> {
result
}
pub struct EISAName {
pub struct EisaName {
value: DWord,
}
impl EISAName {
impl EisaName {
pub fn new(name: &str) -> Self {
assert_eq!(name.len(), 7);
@@ -258,11 +252,11 @@ impl EISAName {
| name.chars().nth(6).unwrap().to_digit(16).unwrap())
.swap_bytes();
EISAName { value }
EisaName { value }
}
}
impl Aml for EISAName {
impl Aml for EisaName {
fn to_aml_bytes(&self) -> Vec<u8> {
self.value.to_aml_bytes()
}
@@ -289,8 +283,7 @@ impl Aml for Usize {
}
fn create_aml_string(v: &str) -> Vec<u8> {
let mut data = Vec::new();
data.push(0x0D); /* String Op */
let mut data = vec![0x0D]; /* String Op */
data.extend_from_slice(v.as_bytes());
data.push(0x0); /* NullChar */
data
@@ -374,9 +367,7 @@ impl Memory32Fixed {
impl Aml for Memory32Fixed {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0x86); /* Memory32Fixed */
let mut bytes = vec![0x86]; /* Memory32Fixed */
bytes.append(&mut 9u16.to_le_bytes().to_vec());
// 9 bytes of payload
@@ -390,7 +381,7 @@ impl Aml for Memory32Fixed {
#[derive(Copy, Clone)]
enum AddressSpaceType {
Memory,
IO,
Io,
BusNumber,
}
@@ -421,7 +412,7 @@ impl<T> AddressSpace<T> {
pub fn new_io(min: T, max: T) -> Self {
AddressSpace {
r#type: AddressSpaceType::IO,
r#type: AddressSpaceType::Io,
min,
max,
type_flags: 3, /* EntireRange */
@@ -510,16 +501,16 @@ impl Aml for AddressSpace<u64> {
}
}
pub struct IO {
pub struct Io {
min: u16,
max: u16,
alignment: u8,
length: u8,
}
impl IO {
impl Io {
pub fn new(min: u16, max: u16, alignment: u8, length: u8) -> Self {
IO {
Io {
min,
max,
alignment,
@@ -528,11 +519,10 @@ impl IO {
}
}
impl Aml for IO {
impl Aml for Io {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
let mut bytes = vec![0x47]; /* Io Port Descriptor */
bytes.push(0x47); /* IO Port Descriptor */
bytes.push(1); /* IODecode16 */
bytes.append(&mut self.min.to_le_bytes().to_vec());
bytes.append(&mut self.max.to_le_bytes().to_vec());
@@ -571,9 +561,7 @@ impl Interrupt {
impl Aml for Interrupt {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0x89); /* Extended IRQ Descriptor */
let mut bytes = vec![0x89]; /* Extended IRQ Descriptor */
bytes.append(&mut 6u16.to_le_bytes().to_vec());
let flags = (self.shared as u8) << 3
| (self.active_low as u8) << 2
@@ -699,8 +687,7 @@ impl<'a> Return<'a> {
impl<'a> Aml for Return<'a> {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0xa4); /* ReturnOp */
let mut bytes = vec![0xa4]; /* ReturnOp */
bytes.append(&mut self.value.to_aml_bytes());
bytes
}
@@ -788,14 +775,14 @@ impl Aml for Field {
#[derive(Clone, Copy)]
pub enum OpRegionSpace {
SystemMemory,
SystemIO,
PCIConfig,
SystemIo,
PConfig,
EmbeddedControl,
SMBus,
SystemCMOS,
Smbus,
SystemCmos,
PciBarTarget,
IPMI,
GeneralPurposeIO,
Ipmi,
GeneralPurposeIo,
GenericSerialBus,
}
@@ -876,8 +863,7 @@ impl<'a> Equal<'a> {
impl<'a> Aml for Equal<'a> {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0x93); /* LEqualOp */
let mut bytes = vec![0x93]; /* LEqualOp */
bytes.extend_from_slice(&self.left.to_aml_bytes());
bytes.extend_from_slice(&self.right.to_aml_bytes());
bytes
@@ -897,8 +883,7 @@ impl<'a> LessThan<'a> {
impl<'a> Aml for LessThan<'a> {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0x95); /* LLessOp */
let mut bytes = vec![0x95]; /* LLessOp */
bytes.extend_from_slice(&self.left.to_aml_bytes());
bytes.extend_from_slice(&self.right.to_aml_bytes());
bytes
@@ -940,8 +925,7 @@ impl<'a> Store<'a> {
impl<'a> Aml for Store<'a> {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0x70); /* StoreOp */
let mut bytes = vec![0x70]; /* StoreOp */
bytes.extend_from_slice(&self.value.to_aml_bytes());
bytes.extend_from_slice(&self.name.to_aml_bytes());
bytes
@@ -961,8 +945,7 @@ impl Mutex {
impl Aml for Mutex {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0x5b); /* ExtOpPrefix */
let mut bytes = vec![0x5b]; /* ExtOpPrefix */
bytes.push(0x01); /* MutexOp */
bytes.extend_from_slice(&self.path.to_aml_bytes());
bytes.push(self.sync_level);
@@ -983,8 +966,7 @@ impl Acquire {
impl Aml for Acquire {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0x5b); /* ExtOpPrefix */
let mut bytes = vec![0x5b]; /* ExtOpPrefix */
bytes.push(0x23); /* AcquireOp */
bytes.extend_from_slice(&self.mutex.to_aml_bytes());
bytes.extend_from_slice(&self.timeout.to_le_bytes());
@@ -1004,8 +986,7 @@ impl Release {
impl Aml for Release {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0x5b); /* ExtOpPrefix */
let mut bytes = vec![0x5b]; /* ExtOpPrefix */
bytes.push(0x27); /* ReleaseOp */
bytes.extend_from_slice(&self.mutex.to_aml_bytes());
bytes
@@ -1025,8 +1006,7 @@ impl<'a> Notify<'a> {
impl<'a> Aml for Notify<'a> {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0x86); /* NotifyOp */
let mut bytes = vec![0x86]; /* NotifyOp */
bytes.extend_from_slice(&self.object.to_aml_bytes());
bytes.extend_from_slice(&self.value.to_aml_bytes());
bytes
@@ -1082,8 +1062,7 @@ macro_rules! binary_op {
impl<'a> Aml for $name<'a> {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push($opcode); /* Op for the binary operator */
let mut bytes = vec![$opcode]; /* Op for the binary operator */
bytes.extend_from_slice(&self.a.to_aml_bytes());
bytes.extend_from_slice(&self.b.to_aml_bytes());
bytes.extend_from_slice(&self.target.to_aml_bytes());
@@ -1180,8 +1159,7 @@ impl<'a, T> CreateField<'a, T> {
impl<'a> Aml for CreateField<'a, u64> {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0x8f); /* CreateQWordFieldOp */
let mut bytes = vec![0x8f]; /* CreateQWordFieldOp */
bytes.extend_from_slice(&self.buffer.to_aml_bytes());
bytes.extend_from_slice(&self.offset.to_aml_bytes());
bytes.extend_from_slice(&self.field.to_aml_bytes());
@@ -1191,8 +1169,7 @@ impl<'a> Aml for CreateField<'a, u64> {
impl<'a> Aml for CreateField<'a, u32> {
fn to_aml_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0x8a); /* CreateDWordFieldOp */
let mut bytes = vec![0x8a]; /* CreateDWordFieldOp */
bytes.extend_from_slice(&self.buffer.to_aml_bytes());
bytes.extend_from_slice(&self.offset.to_aml_bytes());
bytes.extend_from_slice(&self.field.to_aml_bytes());
@@ -1235,12 +1212,12 @@ mod tests {
Device::new(
"_SB_.COM1".into(),
vec![
&Name::new("_HID".into(), &EISAName::new("PNP0501")),
&Name::new("_HID".into(), &EisaName::new("PNP0501")),
&Name::new(
"_CRS".into(),
&ResourceTemplate::new(vec![
&Interrupt::new(true, true, false, false, 4),
&IO::new(0x3f8, 0x3f8, 0, 0x8)
&Io::new(0x3f8, 0x3f8, 0, 0x8)
])
)
]
@@ -1476,7 +1453,7 @@ mod tests {
"_CRS".into(),
&ResourceTemplate::new(vec![
&Interrupt::new(true, true, false, false, 4),
&IO::new(0x3f8, 0x3f8, 0, 0x8)
&Io::new(0x3f8, 0x3f8, 0, 0x8)
])
)
.to_aml_bytes(),
@@ -1519,7 +1496,7 @@ mod tests {
#[test]
fn test_eisa_name() {
assert_eq!(
Name::new("_HID".into(), &EISAName::new("PNP0501")).to_aml_bytes(),
Name::new("_HID".into(), &EisaName::new("PNP0501")).to_aml_bytes(),
[0x08, 0x5F, 0x48, 0x49, 0x44, 0x0C, 0x41, 0xD0, 0x05, 0x01],
)
}
@@ -1665,14 +1642,14 @@ mod tests {
#[test]
fn test_op_region() {
/*
OperationRegion (PRST, SystemIO, 0x0CD8, 0x0C)
OperationRegion (PRST, SystemIo, 0x0CD8, 0x0C)
*/
let op_region_data = [
0x5Bu8, 0x80, 0x50, 0x52, 0x53, 0x54, 0x01, 0x0B, 0xD8, 0x0C, 0x0A, 0x0C,
];
assert_eq!(
OpRegion::new("PRST".into(), OpRegionSpace::SystemIO, 0xcd8, 0xc).to_aml_bytes(),
OpRegion::new("PRST".into(), OpRegionSpace::SystemIo, 0xcd8, 0xc).to_aml_bytes(),
&op_region_data[..]
);
}
@@ -1766,7 +1743,7 @@ mod tests {
Device::new(
"_SB_.MHPC".into(),
vec![
&Name::new("_HID".into(), &EISAName::new("PNP0A06")),
&Name::new("_HID".into(), &EisaName::new("PNP0A06")),
&mutex,
&Method::new(
"TEST".into(),
@@ -1807,7 +1784,7 @@ mod tests {
Device::new(
"_SB_.MHPC".into(),
vec![
&Name::new("_HID".into(), &EISAName::new("PNP0A06")),
&Name::new("_HID".into(), &EisaName::new("PNP0A06")),
&Method::new(
"TEST".into(),
0,
@@ -1848,7 +1825,7 @@ mod tests {
Device::new(
"_SB_.MHPC".into(),
vec![
&Name::new("_HID".into(), &EISAName::new("PNP0A06")),
&Name::new("_HID".into(), &EisaName::new("PNP0A06")),
&Method::new(
"TEST".into(),
0,

View File

@@ -7,7 +7,7 @@ use vm_memory::ByteValued;
#[repr(packed)]
#[derive(Clone, Copy, Default)]
pub struct RSDP {
pub struct Rsdp {
pub signature: [u8; 8],
pub checksum: u8,
pub oem_id: [u8; 6],
@@ -19,17 +19,17 @@ pub struct RSDP {
_reserved: [u8; 3],
}
unsafe impl ByteValued for RSDP {}
unsafe impl ByteValued for Rsdp {}
impl RSDP {
impl Rsdp {
pub fn new(oem_id: [u8; 6], xsdt_addr: u64) -> Self {
let mut rsdp = RSDP {
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,
length: std::mem::size_of::<Rsdp>() as u32,
xsdt_addr,
extended_checksum: 0,
_reserved: [0; 3],
@@ -41,18 +41,18 @@ impl RSDP {
}
pub fn len() -> usize {
std::mem::size_of::<RSDP>()
std::mem::size_of::<Rsdp>()
}
}
#[cfg(test)]
mod tests {
use super::RSDP;
use super::Rsdp;
use vm_memory::bytes::ByteValued;
#[test]
fn test_rsdp() {
let rsdp = RSDP::new(*b"CHYPER", 0xdead_beef);
let rsdp = Rsdp::new(*b"CHYPER", 0xdead_beef);
let sum = rsdp
.as_slice()
.iter()

View File

@@ -13,23 +13,23 @@ pub struct GenericAddress {
}
impl GenericAddress {
pub fn io_port_address(address: u16) -> Self {
pub fn io_port_address<T>(address: u16) -> Self {
GenericAddress {
address_space_id: 1,
register_bit_width: 8,
register_bit_width: 8 * std::mem::size_of::<T>() as u8,
register_bit_offset: 0,
access_size: 1,
access_size: std::mem::size_of::<T>() as u8,
address: u64::from(address),
}
}
}
pub struct SDT {
pub struct Sdt {
data: Vec<u8>,
}
#[allow(clippy::len_without_is_empty)]
impl SDT {
impl Sdt {
pub fn new(
signature: [u8; 4],
length: u32,
@@ -53,7 +53,7 @@ impl SDT {
assert_eq!(data.len(), 36);
data.resize(length as usize, 0);
let mut sdt = SDT { data };
let mut sdt = Sdt { data };
sdt.update_checksum();
sdt
@@ -117,11 +117,11 @@ impl SDT {
#[cfg(test)]
mod tests {
use super::SDT;
use super::Sdt;
#[test]
fn test_sdt() {
let mut sdt = SDT::new(*b"TEST", 40, 1, *b"CLOUDH", *b"TESTTEST", 1);
let mut sdt = Sdt::new(*b"TEST", 40, 1, *b"CLOUDH", *b"TESTTEST", 1);
let sum: u8 = sdt
.as_slice()
.iter()

5
api_client/Cargo.toml Normal file
View File

@@ -0,0 +1,5 @@
[package]
name = "api_client"
version = "0.1.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2018"

175
api_client/src/lib.rs Normal file
View File

@@ -0,0 +1,175 @@
// Copyright © 2020 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
use std::fmt;
use std::io::{Read, Write};
#[derive(Debug)]
pub enum Error {
Socket(std::io::Error),
StatusCodeParsing(std::num::ParseIntError),
MissingProtocol,
ContentLengthParsing(std::num::ParseIntError),
ServerResponse(StatusCode, Option<String>),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Error::*;
match self {
Socket(e) => write!(f, "Error writing to or reading from HTTP socket: {}", e),
StatusCodeParsing(e) => write!(f, "Error parsing HTTP status code: {}", e),
MissingProtocol => write!(f, "HTTP output is missing protocol statement"),
ContentLengthParsing(e) => write!(f, "Error parsing HTTP Content-Length field: {}", e),
ServerResponse(s, o) => {
if let Some(o) = o {
write!(f, "Server responded with an error: {:?}: {}", s, o)
} else {
write!(f, "Server responded with an error: {:?}", s)
}
}
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum StatusCode {
Continue,
Ok,
NoContent,
BadRequest,
NotFound,
InternalServerError,
NotImplemented,
Unknown,
}
impl StatusCode {
fn from_raw(code: usize) -> StatusCode {
match code {
100 => StatusCode::Continue,
200 => StatusCode::Ok,
204 => StatusCode::NoContent,
400 => StatusCode::BadRequest,
404 => StatusCode::NotFound,
500 => StatusCode::InternalServerError,
501 => StatusCode::NotImplemented,
_ => StatusCode::Unknown,
}
}
fn parse(code: &str) -> Result<StatusCode, Error> {
Ok(StatusCode::from_raw(
code.trim().parse().map_err(Error::StatusCodeParsing)?,
))
}
fn is_server_error(self) -> bool {
!matches!(
self,
StatusCode::Ok | StatusCode::Continue | StatusCode::NoContent
)
}
}
fn get_header<'a>(res: &'a str, header: &'a str) -> Option<&'a str> {
let header_str = format!("{}: ", header);
if let Some(o) = res.find(&header_str) {
Some(&res[o + header_str.len()..o + res[o..].find('\r').unwrap()])
} else {
None
}
}
fn get_status_code(res: &str) -> Result<StatusCode, Error> {
if let Some(o) = res.find("HTTP/1.1") {
Ok(StatusCode::parse(
&res[o + "HTTP/1.1 ".len()..res[o..].find('\r').unwrap()],
)?)
} else {
Err(Error::MissingProtocol)
}
}
fn parse_http_response(socket: &mut dyn Read) -> Result<Option<String>, Error> {
let mut res = String::new();
let mut body_offset = None;
let mut content_length: Option<usize> = None;
loop {
let mut bytes = vec![0; 256];
let count = socket.read(&mut bytes).map_err(Error::Socket)?;
res.push_str(std::str::from_utf8(&bytes[0..count]).unwrap());
// End of headers
if let Some(o) = res.find("\r\n\r\n") {
body_offset = Some(o + "\r\n\r\n".len());
// With all headers available we can see if there is any body
content_length = if let Some(length) = get_header(&res, "Content-Length") {
Some(length.trim().parse().map_err(Error::ContentLengthParsing)?)
} else {
None
};
if content_length.is_none() {
break;
}
}
if let Some(body_offset) = body_offset {
if let Some(content_length) = content_length {
if res.len() >= content_length + body_offset {
break;
}
}
}
}
let body_string = content_length.and(Some(String::from(&res[body_offset.unwrap()..])));
let status_code = get_status_code(&res)?;
if status_code.is_server_error() {
Err(Error::ServerResponse(status_code, body_string))
} else {
Ok(body_string)
}
}
pub fn simple_api_command<T: Read + Write>(
socket: &mut T,
method: &str,
c: &str,
request_body: Option<&str>,
) -> Result<(), Error> {
socket
.write_all(
format!(
"{} /api/v1/vm.{} HTTP/1.1\r\nHost: localhost\r\nAccept: */*\r\n",
method, c
)
.as_bytes(),
)
.map_err(Error::Socket)?;
if let Some(request_body) = request_body {
socket
.write_all(format!("Content-Length: {}\r\n", request_body.len()).as_bytes())
.map_err(Error::Socket)?;
}
socket.write_all(b"\r\n").map_err(Error::Socket)?;
if let Some(request_body) = request_body {
socket
.write_all(request_body.as_bytes())
.map_err(Error::Socket)?;
}
socket.flush().map_err(Error::Socket)?;
if let Some(body) = parse_http_response(socket)? {
println!("{}", body);
}
Ok(())
}

View File

@@ -6,20 +6,21 @@ authors = ["The Chromium OS Authors"]
[features]
default = []
acpi = ["acpi_tables"]
tdx = []
[dependencies]
byteorder = "1.3.4"
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch" }
kvm-ioctls = { git = "https://github.com/cloud-hypervisor/kvm-ioctls", branch = "ch" }
libc = "0.2.71"
vm-memory = { version = "0.2.1", features = ["backend-mmap"] }
acpi_tables = { path = "../acpi_tables", optional = true }
anyhow = "1.0"
arch_gen = { path = "../arch_gen" }
byteorder = "1.4.3"
hypervisor = { path = "../hypervisor" }
libc = "0.2.91"
linux-loader = { version = "0.3.0", features = ["elf", "bzimage", "pe"] }
log = "0.4.14"
serde = {version = ">=1.0.27", features = ["rc"] }
serde_derive = ">=1.0.27"
serde_json = ">=1.0.9"
thiserror = "1.0"
vm-memory = { version = "0.5.0", features = ["backend-mmap"] }
vm-migration = { path = "../vm-migration" }
[dependencies.linux-loader]
git = "https://github.com/rust-vmm/linux-loader"
features = ["elf", "bzimage"]
[dev-dependencies]
rand = "0.7.3"

View File

@@ -16,15 +16,23 @@ use std::{io, result};
use super::super::DeviceType;
use super::super::InitramfsConfig;
use super::get_fdt_addr;
use super::gic::GICDevice;
use super::layout::FDT_MAX_SIZE;
use crate::aarch64::fdt::Error::CstringFDTTransform;
use super::gic::GicDevice;
use super::layout::{
FDT_MAX_SIZE, MEM_32BIT_DEVICES_SIZE, MEM_32BIT_DEVICES_START, PCI_MMCONFIG_SIZE,
PCI_MMCONFIG_START,
};
use crate::aarch64::fdt::Error::CstringFdtTransform;
use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryError, GuestMemoryMmap};
// This is a value for uniquely identifying the FDT node declaring the interrupt controller.
const GIC_PHANDLE: u32 = 1;
// This is a value for uniquely identifying the FDT node declaring the MSI controller.
const MSI_PHANDLE: u32 = 2;
// This is a value for uniquely identifying the FDT node containing the clock definition.
const CLOCK_PHANDLE: u32 = 2;
const CLOCK_PHANDLE: u32 = 3;
// This is a value for uniquely identifying the FDT node containing the gpio controller.
const GPIO_PHANDLE: u32 = 4;
// Read the documentation specified when appending the root node to the FDT.
const ADDRESS_CELLS: u32 = 0x2;
const SIZE_CELLS: u32 = 0x2;
@@ -39,6 +47,10 @@ const GIC_FDT_IRQ_TYPE_PPI: u32 = 1;
const IRQ_TYPE_EDGE_RISING: u32 = 1;
const IRQ_TYPE_LEVEL_HI: u32 = 4;
// Keys and Buttons
// System Power Down
const KEY_POWER: u32 = 116;
// This links to libfdt which handles the creation of the binary blob
// flattened device tree (fdt) that is passed to the kernel and indicates
// the hardware configuration of the machine.
@@ -56,7 +68,7 @@ extern "C" {
}
/// Trait for devices to be added to the Flattened Device Tree.
pub trait DeviceInfoForFDT {
pub trait DeviceInfoForFdt {
/// Returns the address where this device will be loaded.
fn addr(&self) -> u64;
/// Returns the associated interrupt for this device.
@@ -69,30 +81,31 @@ pub trait DeviceInfoForFDT {
#[derive(Debug)]
pub enum Error {
/// Failed to append node to the FDT.
AppendFDTNode(io::Error),
AppendFdtNode(io::Error),
/// Failed to append a property to the FDT.
AppendFDTProperty(io::Error),
AppendFdtProperty(io::Error),
/// Syscall for creating FDT failed.
CreateFDT(io::Error),
CreateFdt(io::Error),
/// Failed to obtain a C style string.
CstringFDTTransform(NulError),
CstringFdtTransform(NulError),
/// Failure in calling syscall for terminating this FDT.
FinishFDTReserveMap(io::Error),
FinishFdtReserveMap(io::Error),
/// Failure in writing FDT in memory.
WriteFDTToMemory(GuestMemoryError),
WriteFdtToMemory(GuestMemoryError),
}
type Result<T> = result::Result<T, Error>;
/// Creates the flattened device tree for this aarch64 VM.
pub fn create_fdt<T: DeviceInfoForFDT + Clone + Debug>(
pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
guest_mem: &GuestMemoryMmap,
cmdline: &CStr,
vcpu_mpidr: Vec<u64>,
device_info: &HashMap<(DeviceType, String), T>,
gic_device: &Box<dyn GICDevice>,
device_info: &HashMap<(DeviceType, String), T, S>,
gic_device: &dyn GicDevice,
initrd: &Option<InitramfsConfig>,
pci_space_address: &(u64, u64),
) -> Result<Vec<u8>> {
// Alocate stuff necessary for the holding the blob.
// Allocate stuff necessary for the holding the blob.
let mut fdt = vec![0; FDT_MAX_SIZE];
allocate_fdt(&mut fdt)?;
@@ -119,6 +132,7 @@ pub fn create_fdt<T: DeviceInfoForFDT + Clone + Debug>(
create_clock_node(&mut fdt)?;
create_psci_node(&mut fdt)?;
create_devices_node(&mut fdt, device_info)?;
create_pci_nodes(&mut fdt, pci_space_address.0, pci_space_address.1)?;
// End Header node.
append_end_node(&mut fdt)?;
@@ -131,7 +145,7 @@ pub fn create_fdt<T: DeviceInfoForFDT + Clone + Debug>(
let fdt_address = GuestAddress(get_fdt_addr(&guest_mem));
guest_mem
.write_slice(fdt_final.as_slice(), fdt_address)
.map_err(Error::WriteFDTToMemory)?;
.map_err(Error::WriteFdtToMemory)?;
Ok(fdt_final)
}
@@ -141,7 +155,7 @@ fn allocate_fdt(fdt: &mut Vec<u8>) -> Result<()> {
let mut fdt_ret = unsafe { fdt_create(fdt.as_mut_ptr() as *mut c_void, FDT_MAX_SIZE as c_int) };
if fdt_ret != 0 {
return Err(Error::CreateFDT(io::Error::last_os_error()));
return Err(Error::CreateFdt(io::Error::last_os_error()));
}
// The flattened device trees created with fdt_create() contains a list of
@@ -152,7 +166,7 @@ fn allocate_fdt(fdt: &mut Vec<u8>) -> Result<()> {
// Safe since we previously allocated this array.
fdt_ret = unsafe { fdt_finish_reservemap(fdt.as_mut_ptr() as *mut c_void) };
if fdt_ret != 0 {
return Err(Error::FinishFDTReserveMap(io::Error::last_os_error()));
return Err(Error::FinishFdtReserveMap(io::Error::last_os_error()));
}
Ok(())
}
@@ -161,7 +175,7 @@ fn finish_fdt(from_fdt: &mut Vec<u8>, to_fdt: &mut Vec<u8>) -> Result<()> {
// Safe since we allocated `fdt_final` and previously passed in its size.
let mut fdt_ret = unsafe { fdt_finish(from_fdt.as_mut_ptr() as *mut c_void) };
if fdt_ret != 0 {
return Err(Error::FinishFDTReserveMap(io::Error::last_os_error()));
return Err(Error::FinishFdtReserveMap(io::Error::last_os_error()));
}
// Safe because we allocated both arrays with the correct size.
@@ -173,25 +187,25 @@ fn finish_fdt(from_fdt: &mut Vec<u8>, to_fdt: &mut Vec<u8>) -> Result<()> {
)
};
if fdt_ret != 0 {
return Err(Error::FinishFDTReserveMap(io::Error::last_os_error()));
return Err(Error::FinishFdtReserveMap(io::Error::last_os_error()));
}
// Safe since we allocated `to_fdt`.
fdt_ret = unsafe { fdt_pack(to_fdt.as_mut_ptr() as *mut c_void) };
if fdt_ret != 0 {
return Err(Error::FinishFDTReserveMap(io::Error::last_os_error()));
return Err(Error::FinishFdtReserveMap(io::Error::last_os_error()));
}
Ok(())
}
// Following are auxiliary functions for appending nodes to FDT.
fn append_begin_node(fdt: &mut Vec<u8>, name: &str) -> Result<()> {
let cstr_name = CString::new(name).map_err(CstringFDTTransform)?;
let cstr_name = CString::new(name).map_err(CstringFdtTransform)?;
// Safe because we allocated fdt and converted name to a CString
let fdt_ret = unsafe { fdt_begin_node(fdt.as_mut_ptr() as *mut c_void, cstr_name.as_ptr()) };
if fdt_ret != 0 {
return Err(Error::AppendFDTNode(io::Error::last_os_error()));
return Err(Error::AppendFdtNode(io::Error::last_os_error()));
}
Ok(())
}
@@ -200,7 +214,7 @@ fn append_end_node(fdt: &mut Vec<u8>) -> Result<()> {
// Safe because we allocated fdt.
let fdt_ret = unsafe { fdt_end_node(fdt.as_mut_ptr() as *mut c_void) };
if fdt_ret != 0 {
return Err(Error::AppendFDTNode(io::Error::last_os_error()));
return Err(Error::AppendFdtNode(io::Error::last_os_error()));
}
Ok(())
}
@@ -215,13 +229,13 @@ fn append_property_u64(fdt: &mut Vec<u8>, name: &str, val: u64) -> Result<()> {
}
fn append_property_string(fdt: &mut Vec<u8>, name: &str, value: &str) -> Result<()> {
let cstr_value = CString::new(value).map_err(CstringFDTTransform)?;
let cstr_value = CString::new(value).map_err(CstringFdtTransform)?;
append_property_cstring(fdt, name, &cstr_value)
}
fn append_property_cstring(fdt: &mut Vec<u8>, name: &str, cstr_value: &CStr) -> Result<()> {
let value_bytes = cstr_value.to_bytes_with_nul();
let cstr_name = CString::new(name).map_err(CstringFDTTransform)?;
let cstr_name = CString::new(name).map_err(CstringFdtTransform)?;
// Safe because we allocated fdt, converted name and value to CStrings
let fdt_ret = unsafe {
fdt_property(
@@ -232,13 +246,13 @@ fn append_property_cstring(fdt: &mut Vec<u8>, name: &str, cstr_value: &CStr) ->
)
};
if fdt_ret != 0 {
return Err(Error::AppendFDTProperty(io::Error::last_os_error()));
return Err(Error::AppendFdtProperty(io::Error::last_os_error()));
}
Ok(())
}
fn append_property_null(fdt: &mut Vec<u8>, name: &str) -> Result<()> {
let cstr_name = CString::new(name).map_err(CstringFDTTransform)?;
let cstr_name = CString::new(name).map_err(CstringFdtTransform)?;
// Safe because we allocated fdt, converted name to a CString
let fdt_ret = unsafe {
@@ -250,13 +264,13 @@ fn append_property_null(fdt: &mut Vec<u8>, name: &str) -> Result<()> {
)
};
if fdt_ret != 0 {
return Err(Error::AppendFDTProperty(io::Error::last_os_error()));
return Err(Error::AppendFdtProperty(io::Error::last_os_error()));
}
Ok(())
}
fn append_property(fdt: &mut Vec<u8>, name: &str, val: &[u8]) -> Result<()> {
let cstr_name = CString::new(name).map_err(CstringFDTTransform)?;
let cstr_name = CString::new(name).map_err(CstringFdtTransform)?;
let val_ptr = val.as_ptr() as *const c_void;
// Safe because we allocated fdt and converted name to a CString
@@ -269,7 +283,7 @@ fn append_property(fdt: &mut Vec<u8>, name: &str, val: &[u8]) -> Result<()> {
)
};
if fdt_ret != 0 {
return Err(Error::AppendFDTProperty(io::Error::last_os_error()));
return Err(Error::AppendFdtProperty(io::Error::last_os_error()));
}
Ok(())
}
@@ -301,7 +315,7 @@ fn generate_prop64(cells: &[u64]) -> Vec<u8> {
}
// Following are the auxiliary function for creating the different nodes that we append to our FDT.
fn create_cpu_nodes(fdt: &mut Vec<u8>, vcpu_mpidr: &Vec<u64>) -> Result<()> {
fn create_cpu_nodes(fdt: &mut Vec<u8>, vcpu_mpidr: &[u64]) -> Result<()> {
// See https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/arm/cpus.yaml.
append_begin_node(fdt, "cpus")?;
// As per documentation, on ARM v8 64-bit systems value should be set to 2.
@@ -309,7 +323,7 @@ fn create_cpu_nodes(fdt: &mut Vec<u8>, vcpu_mpidr: &Vec<u64>) -> Result<()> {
append_property_u32(fdt, "#size-cells", 0x0)?;
let num_cpus = vcpu_mpidr.len();
for cpu_index in 0..num_cpus {
for (cpu_index, mpidr) in vcpu_mpidr.iter().enumerate().take(num_cpus) {
let cpu_name = format!("cpu@{:x}", cpu_index);
append_begin_node(fdt, &cpu_name)?;
append_property_string(fdt, "device_type", "cpu")?;
@@ -320,7 +334,7 @@ fn create_cpu_nodes(fdt: &mut Vec<u8>, vcpu_mpidr: &Vec<u64>) -> Result<()> {
}
// Set the field to first 24 bits of the MPIDR - Multiprocessor Affinity Register.
// See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0488c/BABHBJCI.html.
append_property_u64(fdt, "reg", vcpu_mpidr[cpu_index] & 0x7FFFFF)?;
append_property_u64(fdt, "reg", mpidr & 0x7FFFFF)?;
append_end_node(fdt)?;
}
append_end_node(fdt)?;
@@ -366,7 +380,7 @@ fn create_chosen_node(
Ok(())
}
fn create_gic_node(fdt: &mut Vec<u8>, gic_device: &Box<dyn GICDevice>) -> Result<()> {
fn create_gic_node(fdt: &mut Vec<u8>, gic_device: &dyn GicDevice) -> Result<()> {
let gic_reg_prop = generate_prop64(gic_device.device_properties());
append_begin_node(fdt, "intc")?;
@@ -389,6 +403,17 @@ fn create_gic_node(fdt: &mut Vec<u8>, gic_device: &Box<dyn GICDevice>) -> Result
let gic_intr_prop = generate_prop32(&gic_intr);
append_property(fdt, "interrupts", &gic_intr_prop)?;
if gic_device.msi_compatible() {
append_begin_node(fdt, "msic")?;
append_property_string(fdt, "compatible", gic_device.msi_compatibility())?;
append_property_null(fdt, "msi-controller")?;
append_property_u32(fdt, "phandle", MSI_PHANDLE)?;
let msi_reg_prop = generate_prop64(gic_device.msi_properties());
append_property(fdt, "reg", &msi_reg_prop)?;
append_end_node(fdt)?;
}
append_end_node(fdt)?;
Ok(())
@@ -447,7 +472,7 @@ fn create_psci_node(fdt: &mut Vec<u8>) -> Result<()> {
Ok(())
}
fn create_virtio_node<T: DeviceInfoForFDT + Clone + Debug>(
fn create_virtio_node<T: DeviceInfoForFdt + Clone + Debug>(
fdt: &mut Vec<u8>,
dev_info: &T,
) -> Result<()> {
@@ -464,15 +489,16 @@ fn create_virtio_node<T: DeviceInfoForFDT + Clone + Debug>(
Ok(())
}
fn create_serial_node<T: DeviceInfoForFDT + Clone + Debug>(
fn create_serial_node<T: DeviceInfoForFdt + Clone + Debug>(
fdt: &mut Vec<u8>,
dev_info: &T,
) -> Result<()> {
let compatible = b"arm,pl011\0arm,primecell\0";
let serial_reg_prop = generate_prop64(&[dev_info.addr(), dev_info.length()]);
let irq = generate_prop32(&[GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_EDGE_RISING]);
append_begin_node(fdt, &format!("uart@{:x}", dev_info.addr()))?;
append_property_string(fdt, "compatible", "ns16550a")?;
append_begin_node(fdt, &format!("pl011@{:x}", dev_info.addr()))?;
append_property(fdt, "compatible", compatible)?;
append_property(fdt, "reg", &serial_reg_prop)?;
append_property_u32(fdt, "clocks", CLOCK_PHANDLE)?;
append_property_string(fdt, "clock-names", "apb_pclk")?;
@@ -482,7 +508,7 @@ fn create_serial_node<T: DeviceInfoForFDT + Clone + Debug>(
Ok(())
}
fn create_rtc_node<T: DeviceInfoForFDT + Clone + Debug>(
fn create_rtc_node<T: DeviceInfoForFdt + Clone + Debug>(
fdt: &mut Vec<u8>,
dev_info: &T,
) -> Result<()> {
@@ -500,16 +526,52 @@ fn create_rtc_node<T: DeviceInfoForFDT + Clone + Debug>(
Ok(())
}
fn create_devices_node<T: DeviceInfoForFDT + Clone + Debug>(
fn create_gpio_node<T: DeviceInfoForFdt + Clone + Debug>(
fdt: &mut Vec<u8>,
dev_info: &HashMap<(DeviceType, String), T>,
dev_info: &T,
) -> Result<()> {
// PL061 GPIO controller node
let compatible = b"arm,pl061\0arm,primecell\0";
let gpio_reg_prop = generate_prop64(&[dev_info.addr(), dev_info.length()]);
let irq = generate_prop32(&[GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_EDGE_RISING]);
append_begin_node(fdt, &format!("pl061@{:x}", dev_info.addr()))?;
append_property(fdt, "compatible", compatible)?;
append_property(fdt, "reg", &gpio_reg_prop)?;
append_property(fdt, "interrupts", &irq)?;
append_property_null(fdt, "gpio-controller")?;
append_property_u32(fdt, "#gpio-cells", 2)?;
append_property_u32(fdt, "clocks", CLOCK_PHANDLE)?;
append_property_string(fdt, "clock-names", "apb_pclk")?;
append_property_u32(fdt, "phandle", GPIO_PHANDLE)?;
append_end_node(fdt)?;
// gpio-keys node
append_begin_node(fdt, "/gpio-keys")?;
append_property_string(fdt, "compatible", "gpio-keys")?;
append_property_u32(fdt, "#size-cells", 0)?;
append_property_u32(fdt, "#address-cells", 1)?;
append_begin_node(fdt, "/gpio-keys/poweroff")?;
append_property_string(fdt, "label", "GPIO Key Poweroff")?;
append_property_u32(fdt, "linux,code", KEY_POWER)?;
let gpios = generate_prop32(&[GPIO_PHANDLE, 3, 0]);
append_property(fdt, "gpios", &gpios)?;
append_end_node(fdt)?;
append_end_node(fdt)?;
Ok(())
}
fn create_devices_node<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
fdt: &mut Vec<u8>,
dev_info: &HashMap<(DeviceType, String), T, S>,
) -> Result<()> {
// Create one temp Vec to store all virtio devices
let mut ordered_virtio_device: Vec<&T> = Vec::new();
for ((device_type, _device_id), info) in dev_info {
match device_type {
DeviceType::RTC => create_rtc_node(fdt, info)?,
DeviceType::Gpio => create_gpio_node(fdt, info)?,
DeviceType::Rtc => create_rtc_node(fdt, info)?,
DeviceType::Serial => create_serial_node(fdt, info)?,
DeviceType::Virtio(_) => {
ordered_virtio_device.push(info);
@@ -518,7 +580,11 @@ fn create_devices_node<T: DeviceInfoForFDT + Clone + Debug>(
}
// Sort out virtio devices by address from low to high and insert them into fdt table.
ordered_virtio_device.sort_by(|a, b| a.addr().cmp(&b.addr()));
ordered_virtio_device.sort_by_key(|&a| a.addr());
// Current address allocation strategy in cloud-hypervisor is: the first created device
// will be allocated to higher address. Here we reverse the vector to make sure that
// the older created device will appear in front of the newer created device in FDT.
ordered_virtio_device.reverse();
for ordered_device_info in ordered_virtio_device.drain(..) {
create_virtio_node(fdt, ordered_device_info)?;
}
@@ -526,85 +592,45 @@ fn create_devices_node<T: DeviceInfoForFDT + Clone + Debug>(
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::aarch64::gic::create_gic;
use crate::aarch64::layout;
use kvm_ioctls::Kvm;
fn create_pci_nodes(fdt: &mut Vec<u8>, pci_device_base: u64, pci_device_size: u64) -> Result<()> {
// Add node for PCIe controller.
// See Documentation/devicetree/bindings/pci/host-generic-pci.txt in the kernel
// and https://elinux.org/Device_Tree_Usage.
let ranges = generate_prop32(&[
// mmio addresses
0x2000000, // (ss = 10: 32-bit memory space)
(MEM_32BIT_DEVICES_START.0 >> 32) as u32, // PCI address
MEM_32BIT_DEVICES_START.0 as u32,
(MEM_32BIT_DEVICES_START.0 >> 32) as u32, // CPU address
MEM_32BIT_DEVICES_START.0 as u32,
(MEM_32BIT_DEVICES_SIZE >> 32) as u32, // size
MEM_32BIT_DEVICES_SIZE as u32,
// device addresses
0x3000000, // (ss = 11: 64-bit memory space)
(pci_device_base >> 32) as u32, // PCI address
pci_device_base as u32,
(pci_device_base >> 32) as u32, // CPU address
pci_device_base as u32,
(pci_device_size >> 32) as u32, // size
pci_device_size as u32,
]);
let bus_range = generate_prop32(&[0, 0]); // Only bus 0
let reg = generate_prop64(&[PCI_MMCONFIG_START.0, PCI_MMCONFIG_SIZE]);
const LEN: u64 = 4096;
append_begin_node(fdt, "pci")?;
append_property_string(fdt, "compatible", "pci-host-ecam-generic")?;
append_property_string(fdt, "device_type", "pci")?;
append_property(fdt, "ranges", &ranges)?;
append_property(fdt, "bus-range", &bus_range)?;
append_property_u32(fdt, "#address-cells", 3)?;
append_property_u32(fdt, "#size-cells", 2)?;
append_property(fdt, "reg", &reg)?;
append_property_u32(fdt, "#interrupt-cells", 1)?;
append_property_null(fdt, "interrupt-map")?;
append_property_null(fdt, "interrupt-map-mask")?;
append_property_null(fdt, "dma-coherent")?;
append_property_u32(fdt, "msi-parent", MSI_PHANDLE)?;
append_end_node(fdt)?;
#[derive(Clone, Debug)]
pub struct MMIODeviceInfo {
addr: u64,
irq: u32,
}
impl DeviceInfoForFDT for MMIODeviceInfo {
fn addr(&self) -> u64 {
self.addr
}
fn irq(&self) -> u32 {
self.irq
}
fn length(&self) -> u64 {
LEN
}
}
// The `load` function from the `device_tree` will mistakenly check the actual size
// of the buffer with the allocated size. This works around that.
fn set_size(buf: &mut [u8], pos: usize, val: usize) {
buf[pos] = ((val >> 24) & 0xff) as u8;
buf[pos + 1] = ((val >> 16) & 0xff) as u8;
buf[pos + 2] = ((val >> 8) & 0xff) as u8;
buf[pos + 3] = (val & 0xff) as u8;
}
#[test]
fn test_create_fdt_with_devices() {
let mut regions = Vec::new();
regions.push((
GuestAddress(layout::RAM_64BIT_START),
(layout::FDT_MAX_SIZE + 0x1000) as usize,
));
let mem = GuestMemoryMmap::from_ranges(&regions).expect("Cannot initialize memory");
let dev_info: HashMap<(DeviceType, std::string::String), MMIODeviceInfo> = [
(
(DeviceType::Serial, DeviceType::Serial.to_string()),
MMIODeviceInfo { addr: 0x00, irq: 1 },
),
(
(DeviceType::Virtio(1), "virtio".to_string()),
MMIODeviceInfo {
addr: 0x00 + LEN,
irq: 2,
},
),
(
(DeviceType::RTC, "rtc".to_string()),
MMIODeviceInfo {
addr: 0x00 + 2 * LEN,
irq: 3,
},
),
]
.iter()
.cloned()
.collect();
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let gic = create_gic(&vm, 1).unwrap();
assert!(create_fdt(
&mem,
&CString::new("console=tty0").unwrap(),
vec![0],
&dev_info,
&gic,
&None,
)
.is_ok())
}
Ok(())
}

View File

@@ -1,159 +0,0 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use std::{boxed::Box, result};
use kvm_ioctls::{DeviceFd, VmFd};
use super::gicv2::GICv2;
use super::gicv3::GICv3;
/// Errors thrown while setting up the GIC.
#[derive(Debug)]
pub enum Error {
/// Error while calling KVM ioctl for setting up the global interrupt controller.
CreateGIC(kvm_ioctls::Error),
/// Error while setting device attributes for the GIC.
SetDeviceAttribute(kvm_ioctls::Error),
}
type Result<T> = result::Result<T, Error>;
/// Trait for GIC devices.
pub trait GICDevice: Send + Sync {
/// Returns the file descriptor of the GIC device
fn device_fd(&self) -> &DeviceFd;
/// Returns an array with GIC device properties
fn device_properties(&self) -> &[u64];
/// Returns the number of vCPUs this GIC handles
fn vcpu_count(&self) -> u64;
/// Returns the fdt compatibility property of the device
fn fdt_compatibility(&self) -> &str;
/// Returns the maint_irq fdt property of the device
fn fdt_maint_irq(&self) -> u32;
/// Returns the GIC version of the device
fn version() -> u32
where
Self: Sized;
/// Create the GIC device object
fn create_device(fd: DeviceFd, vcpu_count: u64) -> Box<dyn GICDevice>
where
Self: Sized;
/// Setup the device-specific attributes
fn init_device_attributes(gic_device: &Box<dyn GICDevice>) -> Result<()>
where
Self: Sized;
/// Initialize a GIC device
fn init_device(vm: &VmFd) -> Result<DeviceFd>
where
Self: Sized,
{
let mut gic_device = kvm_bindings::kvm_create_device {
type_: Self::version(),
fd: 0,
flags: 0,
};
vm.create_device(&mut gic_device).map_err(Error::CreateGIC)
}
/// Set a GIC device attribute
fn set_device_attribute(
fd: &DeviceFd,
group: u32,
attr: u64,
addr: u64,
flags: u32,
) -> Result<()>
where
Self: Sized,
{
let attr = kvm_bindings::kvm_device_attr {
group: group,
attr: attr,
addr: addr,
flags: flags,
};
fd.set_device_attr(&attr)
.map_err(Error::SetDeviceAttribute)?;
Ok(())
}
/// Finalize the setup of a GIC device
fn finalize_device(gic_device: &Box<dyn GICDevice>) -> Result<()>
where
Self: Sized,
{
/* We need to tell the kernel how many irqs to support with this vgic.
* See the `layout` module for details.
*/
let nr_irqs: u32 = super::layout::IRQ_MAX - super::layout::IRQ_BASE + 1;
let nr_irqs_ptr = &nr_irqs as *const u32;
Self::set_device_attribute(
gic_device.device_fd(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
0,
nr_irqs_ptr as u64,
0,
)?;
/* Finalize the GIC.
* See https://code.woboq.org/linux/linux/virt/kvm/arm/vgic/vgic-kvm-device.c.html#211.
*/
Self::set_device_attribute(
gic_device.device_fd(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_CTRL,
u64::from(kvm_bindings::KVM_DEV_ARM_VGIC_CTRL_INIT),
0,
0,
)?;
Ok(())
}
/// Method to initialize the GIC device
fn new(vm: &VmFd, vcpu_count: u64) -> Result<Box<dyn GICDevice>>
where
Self: Sized,
{
let vgic_fd = Self::init_device(vm)?;
let device = Self::create_device(vgic_fd, vcpu_count);
Self::init_device_attributes(&device)?;
Self::finalize_device(&device)?;
Ok(device)
}
}
/// Create a GIC device.
///
/// It will try to create by default a GICv3 device. If that fails it will try
/// to fall-back to a GICv2 device.
pub fn create_gic(vm: &VmFd, vcpu_count: u64) -> Result<Box<dyn GICDevice>> {
GICv3::new(vm, vcpu_count).or_else(|_| GICv2::new(vm, vcpu_count))
}
#[cfg(test)]
mod tests {
use super::*;
use kvm_ioctls::Kvm;
#[test]
fn test_create_gic() {
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
assert!(create_gic(&vm, 1).is_ok());
}
}

View File

@@ -0,0 +1,182 @@
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use super::{Error, Result};
use crate::layout::IRQ_BASE;
use hypervisor::kvm::kvm_bindings::{
kvm_device_attr, KVM_DEV_ARM_VGIC_GRP_DIST_REGS, KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
};
use std::sync::Arc;
/*
Distributor registers as detailed at page 456 from
https://static.docs.arm.com/ihi0069/c/IHI0069C_gic_architecture_specification.pdf.
Address offsets are relative to the Distributor base address defined
by the system memory map. Unless otherwise stated in the register description,
all GIC registers are 32-bits wide.
*/
const GICD_CTLR: u32 = 0x0;
const GICD_STATUSR: u32 = 0x0010;
const GICD_IGROUPR: u32 = 0x0080;
const GICD_ISENABLER: u32 = 0x0100;
const GICD_ICENABLER: u32 = 0x0180;
const GICD_ISPENDR: u32 = 0x0200;
const GICD_ICPENDR: u32 = 0x0280;
const GICD_ISACTIVER: u32 = 0x0300;
const GICD_ICACTIVER: u32 = 0x0380;
const GICD_IPRIORITYR: u32 = 0x0400;
const GICD_ICFGR: u32 = 0x0C00;
const GICD_IROUTER: u32 = 0x6000;
/// This is how we represent the registers of the vgic's distributor.
/// Some of the distributor register )(i.e GICD_STATUSR) are simple
/// registers (i.e they are associated to a 32 bit value).
/// However, there are other registers that have variable lengths since
/// they dedicate some of the 32 bits to some specific interrupt. So, their length
/// depends on the number of interrupts (i.e the ones that are represented as GICD_REG<n>)
/// in the documentation mentioned above.
struct DistReg {
/// Offset from distributor address.
base: u32,
/// Bits per interrupt.
/// Relevant for registers that DO share IRQs.
bpi: u8,
/// Length of the register.
/// Relevant for registers that DO NOT share IRQs.
length: u16,
}
// All or at least the registers we are interested in are 32 bit, so
// we use a constant for size(u32).
const REG_SIZE: u8 = 4;
// Creates a vgic distributor register.
macro_rules! VGIC_DIST_REG {
($base:expr, $bpi:expr, $length:expr) => {
DistReg {
base: $base,
bpi: $bpi,
length: $length,
}
};
}
// List with relevant distributor registers that we will be restoring.
// Order is taken from qemu.
static VGIC_DIST_REGS: &'static [DistReg] = &[
VGIC_DIST_REG!(GICD_STATUSR, 0, 4),
VGIC_DIST_REG!(GICD_ICENABLER, 1, 0),
VGIC_DIST_REG!(GICD_ISENABLER, 1, 0),
VGIC_DIST_REG!(GICD_IGROUPR, 1, 0),
VGIC_DIST_REG!(GICD_IROUTER, 64, 0),
VGIC_DIST_REG!(GICD_ICFGR, 2, 0),
VGIC_DIST_REG!(GICD_ICPENDR, 1, 0),
VGIC_DIST_REG!(GICD_ISPENDR, 1, 0),
VGIC_DIST_REG!(GICD_ICACTIVER, 1, 0),
VGIC_DIST_REG!(GICD_ISACTIVER, 1, 0),
VGIC_DIST_REG!(GICD_IPRIORITYR, 8, 0),
];
fn dist_attr_access(
gic: &Arc<dyn hypervisor::Device>,
offset: u32,
val: &u32,
set: bool,
) -> Result<()> {
let mut gic_dist_attr = kvm_device_attr {
group: KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
attr: offset as u64,
addr: val as *const u32 as u64,
flags: 0,
};
if set {
gic.set_device_attr(&gic_dist_attr)
.map_err(Error::SetDeviceAttribute)?;
} else {
gic.get_device_attr(&mut gic_dist_attr)
.map_err(Error::GetDeviceAttribute)?;
}
Ok(())
}
/// Get the distributor control register.
pub fn read_ctlr(gic: &Arc<dyn hypervisor::Device>) -> Result<u32> {
let val: u32 = 0;
dist_attr_access(gic, GICD_CTLR, &val, false)?;
Ok(val)
}
/// Set the distributor control register.
pub fn write_ctlr(gic: &Arc<dyn hypervisor::Device>, val: u32) -> Result<()> {
dist_attr_access(gic, GICD_CTLR, &val, true)
}
fn get_interrupts_num(gic: &Arc<dyn hypervisor::Device>) -> Result<u32> {
let num_irq = 0;
let mut nr_irqs_attr = kvm_device_attr {
group: KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
attr: 0,
addr: &num_irq as *const u32 as u64,
flags: 0,
};
gic.get_device_attr(&mut nr_irqs_attr)
.map_err(Error::GetDeviceAttribute)?;
Ok(num_irq)
}
fn compute_reg_len(gic: &Arc<dyn hypervisor::Device>, reg: &DistReg, base: u32) -> Result<u32> {
let mut end = base;
let num_irq = get_interrupts_num(gic)?;
if reg.length > 0 {
// This is the single type register (i.e one that is not DIST_X<n>) and for which
// the bpi is 0.
// Look in the kernel for REGISTER_DESC_WITH_LENGTH.
end = base + reg.length as u32;
}
if reg.bpi > 0 {
// This is the type of register that takes into account the number of interrupts
// that the model has. It is also the type of register where
// a register relates to multiple interrupts.
end = base + (reg.bpi as u32 * (num_irq - IRQ_BASE) / 8);
if reg.bpi as u32 * (num_irq - IRQ_BASE) % 8 > 0 {
end += REG_SIZE as u32;
}
}
Ok(end)
}
/// Set distributor registers of the GIC.
pub fn set_dist_regs(gic: &Arc<dyn hypervisor::Device>, state: &[u32]) -> Result<()> {
let mut idx = 0;
for dreg in VGIC_DIST_REGS {
let mut base = dreg.base + REG_SIZE as u32 * dreg.bpi as u32;
let end = compute_reg_len(gic, &dreg, base)?;
while base < end {
let val = state[idx];
dist_attr_access(gic, base, &val, true)?;
idx += 1;
base += REG_SIZE as u32;
}
}
Ok(())
}
/// Get distributor registers of the GIC.
pub fn get_dist_regs(gic: &Arc<dyn hypervisor::Device>) -> Result<Vec<u32>> {
let mut state = Vec::new();
for dreg in VGIC_DIST_REGS {
let mut base = dreg.base + REG_SIZE as u32 * dreg.bpi as u32;
let end = compute_reg_len(gic, &dreg, base)?;
while base < end {
let val: u32 = 0;
dist_attr_access(gic, base, &val, false)?;
state.push(val);
base += REG_SIZE as u32;
}
}
Ok(state)
}

View File

@@ -0,0 +1,275 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
pub mod kvm {
use crate::aarch64::gic::dist_regs::{get_dist_regs, read_ctlr, set_dist_regs, write_ctlr};
use crate::aarch64::gic::icc_regs::{get_icc_regs, set_icc_regs};
use crate::aarch64::gic::kvm::{save_pending_tables, KvmGicDevice};
use crate::aarch64::gic::redist_regs::{get_redist_regs, set_redist_regs};
use crate::aarch64::gic::GicDevice;
use crate::layout;
use anyhow::anyhow;
use hypervisor::kvm::kvm_bindings;
use std::any::Any;
use std::convert::TryInto;
use std::sync::Arc;
use std::{boxed::Box, result};
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, SnapshotDataSection, Snapshottable,
Transportable,
};
/// Errors thrown while saving/restoring the GICv3.
#[derive(Debug)]
pub enum Error {
/// Error in saving RDIST pending tables into guest RAM.
SavePendingTables(crate::aarch64::gic::Error),
/// Error in saving GIC distributor registers.
SaveDistributorRegisters(crate::aarch64::gic::Error),
/// Error in restoring GIC distributor registers.
RestoreDistributorRegisters(crate::aarch64::gic::Error),
/// Error in saving GIC distributor control registers.
SaveDistributorCtrlRegisters(crate::aarch64::gic::Error),
/// Error in restoring GIC distributor control registers.
RestoreDistributorCtrlRegisters(crate::aarch64::gic::Error),
/// Error in saving GIC redistributor registers.
SaveRedistributorRegisters(crate::aarch64::gic::Error),
/// Error in restoring GIC redistributor registers.
RestoreRedistributorRegisters(crate::aarch64::gic::Error),
/// Error in saving GIC CPU interface registers.
SaveIccRegisters(crate::aarch64::gic::Error),
/// Error in restoring GIC CPU interface registers.
RestoreIccRegisters(crate::aarch64::gic::Error),
}
type Result<T> = result::Result<T, Error>;
pub struct KvmGicV3 {
/// The hypervisor agnostic device
device: Arc<dyn hypervisor::Device>,
/// Vector holding values of GICR_TYPER for each vCPU
gicr_typers: Vec<u64>,
/// GIC device properties, to be used for setting up the fdt entry
properties: [u64; 4],
/// Number of CPUs handled by the device
vcpu_count: u64,
}
#[derive(Serialize, Deserialize)]
pub struct Gicv3State {
dist: Vec<u32>,
rdist: Vec<u32>,
icc: Vec<u32>,
// special register that enables interrupts and affinity routing
gicd_ctlr: u32,
}
impl KvmGicV3 {
// Unfortunately bindgen omits defines that are based on other defines.
// See arch/arm64/include/uapi/asm/kvm.h file from the linux kernel.
pub const SZ_64K: u64 = 0x0001_0000;
const KVM_VGIC_V3_DIST_SIZE: u64 = KvmGicV3::SZ_64K;
const KVM_VGIC_V3_REDIST_SIZE: u64 = (2 * KvmGicV3::SZ_64K);
// Device trees specific constants
pub const ARCH_GIC_V3_MAINT_IRQ: u32 = 9;
/// Get the address of the GIC distributor.
pub fn get_dist_addr() -> u64 {
layout::MAPPED_IO_START - KvmGicV3::KVM_VGIC_V3_DIST_SIZE
}
/// Get the size of the GIC distributor.
pub fn get_dist_size() -> u64 {
KvmGicV3::KVM_VGIC_V3_DIST_SIZE
}
/// Get the address of the GIC redistributors.
pub fn get_redists_addr(vcpu_count: u64) -> u64 {
KvmGicV3::get_dist_addr() - KvmGicV3::get_redists_size(vcpu_count)
}
/// Get the size of the GIC redistributors.
pub fn get_redists_size(vcpu_count: u64) -> u64 {
vcpu_count * KvmGicV3::KVM_VGIC_V3_REDIST_SIZE
}
/// Save the state of GIC.
fn state(&self, gicr_typers: &[u64]) -> Result<Gicv3State> {
// Flush redistributors pending tables to guest RAM.
save_pending_tables(&self.device()).map_err(Error::SavePendingTables)?;
let gicd_ctlr =
read_ctlr(&self.device()).map_err(Error::SaveDistributorCtrlRegisters)?;
let dist_state =
get_dist_regs(&self.device()).map_err(Error::SaveDistributorRegisters)?;
let rdist_state = get_redist_regs(&self.device(), &gicr_typers)
.map_err(Error::SaveRedistributorRegisters)?;
let icc_state =
get_icc_regs(&self.device(), &gicr_typers).map_err(Error::SaveIccRegisters)?;
Ok(Gicv3State {
dist: dist_state,
rdist: rdist_state,
icc: icc_state,
gicd_ctlr,
})
}
/// Restore the state of GIC.
fn set_state(&mut self, gicr_typers: &[u64], state: &Gicv3State) -> Result<()> {
write_ctlr(&self.device(), state.gicd_ctlr)
.map_err(Error::RestoreDistributorCtrlRegisters)?;
set_dist_regs(&self.device(), &state.dist)
.map_err(Error::RestoreDistributorRegisters)?;
set_redist_regs(&self.device(), gicr_typers, &state.rdist)
.map_err(Error::RestoreRedistributorRegisters)?;
set_icc_regs(&self.device(), &gicr_typers, &state.icc)
.map_err(Error::RestoreIccRegisters)?;
Ok(())
}
}
impl GicDevice for KvmGicV3 {
fn device(&self) -> &Arc<dyn hypervisor::Device> {
&self.device
}
fn fdt_compatibility(&self) -> &str {
"arm,gic-v3"
}
fn fdt_maint_irq(&self) -> u32 {
KvmGicV3::ARCH_GIC_V3_MAINT_IRQ
}
fn device_properties(&self) -> &[u64] {
&self.properties
}
fn vcpu_count(&self) -> u64 {
self.vcpu_count
}
fn set_gicr_typers(&mut self, gicr_typers: Vec<u64>) {
self.gicr_typers = gicr_typers;
}
fn as_any_concrete_mut(&mut self) -> &mut dyn Any {
self
}
}
impl KvmGicDevice for KvmGicV3 {
fn version() -> u32 {
kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3
}
fn create_device(
device: Arc<dyn hypervisor::Device>,
vcpu_count: u64,
) -> Box<dyn GicDevice> {
Box::new(KvmGicV3 {
device,
gicr_typers: vec![0; vcpu_count.try_into().unwrap()],
properties: [
KvmGicV3::get_dist_addr(),
KvmGicV3::get_dist_size(),
KvmGicV3::get_redists_addr(vcpu_count),
KvmGicV3::get_redists_size(vcpu_count),
],
vcpu_count,
})
}
fn init_device_attributes(
_vm: &Arc<dyn hypervisor::Vm>,
gic_device: &dyn GicDevice,
) -> crate::aarch64::gic::Result<()> {
/* Setting up the distributor attribute.
We are placing the GIC below 1GB so we need to substract the size of the distributor.
*/
Self::set_device_attribute(
gic_device.device(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_DIST),
&KvmGicV3::get_dist_addr() as *const u64 as u64,
0,
)?;
/* Setting up the redistributors' attribute.
We are calculating here the start of the redistributors address. We have one per CPU.
*/
Self::set_device_attribute(
gic_device.device(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_REDIST),
&KvmGicV3::get_redists_addr(gic_device.vcpu_count()) as *const u64 as u64,
0,
)?;
Ok(())
}
}
pub const GIC_V3_SNAPSHOT_ID: &str = "gic-v3";
impl Snapshottable for KvmGicV3 {
fn id(&self) -> String {
GIC_V3_SNAPSHOT_ID.to_string()
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
let gicr_typers = self.gicr_typers.clone();
let snapshot = serde_json::to_vec(&self.state(&gicr_typers).unwrap())
.map_err(|e| MigratableError::Snapshot(e.into()))?;
let mut gic_v3_snapshot = Snapshot::new(self.id().as_str());
gic_v3_snapshot.add_data_section(SnapshotDataSection {
id: format!("{}-section", self.id()),
snapshot,
});
Ok(gic_v3_snapshot)
}
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
if let Some(gic_v3_section) = snapshot
.snapshot_data
.get(&format!("{}-section", self.id()))
{
let gic_v3_state = match serde_json::from_slice(&gic_v3_section.snapshot) {
Ok(state) => state,
Err(error) => {
return Err(MigratableError::Restore(anyhow!(
"Could not deserialize GICv3 {}",
error
)))
}
};
let gicr_typers = self.gicr_typers.clone();
return self.set_state(&gicr_typers, &gic_v3_state).map_err(|e| {
MigratableError::Restore(anyhow!("Could not restore GICv3 state {:?}", e))
});
}
Err(MigratableError::Restore(anyhow!(
"Could not find GICv3 snapshot section"
)))
}
}
impl Pausable for KvmGicV3 {}
impl Transportable for KvmGicV3 {}
impl Migratable for KvmGicV3 {}
}

View File

@@ -0,0 +1,147 @@
// Copyright 2020 ARM Limited
// SPDX-License-Identifier: Apache-2.0
pub mod kvm {
use std::any::Any;
use std::convert::TryInto;
use std::sync::Arc;
use std::{boxed::Box, result};
type Result<T> = result::Result<T, Error>;
use crate::aarch64::gic::gicv3::kvm::KvmGicV3;
use crate::aarch64::gic::kvm::KvmGicDevice;
use crate::aarch64::gic::{Error, GicDevice};
use hypervisor::kvm::kvm_bindings;
pub struct KvmGicV3Its {
/// The hypervisor agnostic device
device: Arc<dyn hypervisor::Device>,
/// Vector holding values of GICR_TYPER for each vCPU
gicr_typers: Vec<u64>,
/// GIC device properties, to be used for setting up the fdt entry
gic_properties: [u64; 4],
/// MSI device properties, to be used for setting up the fdt entry
msi_properties: [u64; 2],
/// Number of CPUs handled by the device
vcpu_count: u64,
}
impl KvmGicV3Its {
const KVM_VGIC_V3_ITS_SIZE: u64 = (2 * KvmGicV3::SZ_64K);
fn get_msi_size() -> u64 {
KvmGicV3Its::KVM_VGIC_V3_ITS_SIZE
}
fn get_msi_addr(vcpu_count: u64) -> u64 {
KvmGicV3::get_redists_addr(vcpu_count) - KvmGicV3Its::get_msi_size()
}
}
impl GicDevice for KvmGicV3Its {
fn device(&self) -> &Arc<dyn hypervisor::Device> {
&self.device
}
fn fdt_compatibility(&self) -> &str {
"arm,gic-v3"
}
fn msi_compatible(&self) -> bool {
true
}
fn msi_compatibility(&self) -> &str {
"arm,gic-v3-its"
}
fn fdt_maint_irq(&self) -> u32 {
KvmGicV3::ARCH_GIC_V3_MAINT_IRQ
}
fn msi_properties(&self) -> &[u64] {
&self.msi_properties
}
fn device_properties(&self) -> &[u64] {
&self.gic_properties
}
fn vcpu_count(&self) -> u64 {
self.vcpu_count
}
fn set_gicr_typers(&mut self, gicr_typers: Vec<u64>) {
self.gicr_typers = gicr_typers;
}
fn as_any_concrete_mut(&mut self) -> &mut dyn Any {
self
}
}
impl KvmGicDevice for KvmGicV3Its {
fn version() -> u32 {
KvmGicV3::version()
}
fn create_device(
device: Arc<dyn hypervisor::Device>,
vcpu_count: u64,
) -> Box<dyn GicDevice> {
Box::new(KvmGicV3Its {
device,
gicr_typers: vec![0; vcpu_count.try_into().unwrap()],
gic_properties: [
KvmGicV3::get_dist_addr(),
KvmGicV3::get_dist_size(),
KvmGicV3::get_redists_addr(vcpu_count),
KvmGicV3::get_redists_size(vcpu_count),
],
msi_properties: [
KvmGicV3Its::get_msi_addr(vcpu_count),
KvmGicV3Its::get_msi_size(),
],
vcpu_count,
})
}
fn init_device_attributes(
vm: &Arc<dyn hypervisor::Vm>,
gic_device: &dyn GicDevice,
) -> Result<()> {
KvmGicV3::init_device_attributes(vm, gic_device)?;
let mut its_device = kvm_bindings::kvm_create_device {
type_: kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_ITS,
fd: 0,
flags: 0,
};
let its_fd = vm
.create_device(&mut its_device)
.map_err(Error::CreateGic)?;
Self::set_device_attribute(
&its_fd,
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
u64::from(kvm_bindings::KVM_VGIC_ITS_ADDR_TYPE),
&KvmGicV3Its::get_msi_addr(gic_device.vcpu_count()) as *const u64 as u64,
0,
)?;
Self::set_device_attribute(
&its_fd,
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_CTRL,
u64::from(kvm_bindings::KVM_DEV_ARM_VGIC_CTRL_INIT),
0,
0,
)?;
Ok(())
}
}
}

View File

@@ -0,0 +1,196 @@
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use super::{Error, Result};
use hypervisor::kvm::kvm_bindings::{
kvm_device_attr, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, KVM_REG_ARM64_SYSREG_CRM_MASK,
KVM_REG_ARM64_SYSREG_CRM_SHIFT, KVM_REG_ARM64_SYSREG_CRN_MASK, KVM_REG_ARM64_SYSREG_CRN_SHIFT,
KVM_REG_ARM64_SYSREG_OP0_MASK, KVM_REG_ARM64_SYSREG_OP0_SHIFT, KVM_REG_ARM64_SYSREG_OP1_MASK,
KVM_REG_ARM64_SYSREG_OP1_SHIFT, KVM_REG_ARM64_SYSREG_OP2_MASK, KVM_REG_ARM64_SYSREG_OP2_SHIFT,
};
use std::sync::Arc;
const KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT: u32 = 32;
const KVM_DEV_ARM_VGIC_V3_MPIDR_MASK: u64 = 0xffffffff << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT as u64;
const ICC_CTLR_EL1_PRIBITS_SHIFT: u32 = 8;
const ICC_CTLR_EL1_PRIBITS_MASK: u32 = 7 << ICC_CTLR_EL1_PRIBITS_SHIFT;
macro_rules! arm64_vgic_sys_reg {
($name: tt, $op0: tt, $op1: tt, $crn: tt, $crm: tt, $op2: expr) => {
const $name: u64 = ((($op0 as u64) << KVM_REG_ARM64_SYSREG_OP0_SHIFT)
& KVM_REG_ARM64_SYSREG_OP0_MASK as u64)
| ((($op1 as u64) << KVM_REG_ARM64_SYSREG_OP1_SHIFT)
& KVM_REG_ARM64_SYSREG_OP1_MASK as u64)
| ((($crn as u64) << KVM_REG_ARM64_SYSREG_CRN_SHIFT)
& KVM_REG_ARM64_SYSREG_CRN_MASK as u64)
| ((($crm as u64) << KVM_REG_ARM64_SYSREG_CRM_SHIFT)
& KVM_REG_ARM64_SYSREG_CRM_MASK as u64)
| ((($op2 as u64) << KVM_REG_ARM64_SYSREG_OP2_SHIFT)
& KVM_REG_ARM64_SYSREG_OP2_MASK as u64);
};
}
macro_rules! SYS_ICC_AP0Rn_EL1 {
($name: tt, $n: tt) => {
arm64_vgic_sys_reg!($name, 3, 0, 12, 8, (4 | $n));
};
}
macro_rules! SYS_ICC_AP1Rn_EL1 {
($name: tt, $n: tt) => {
arm64_vgic_sys_reg!($name, 3, 0, 12, 9, $n);
};
}
arm64_vgic_sys_reg!(SYS_ICC_SRE_EL1, 3, 0, 12, 12, 5);
arm64_vgic_sys_reg!(SYS_ICC_CTLR_EL1, 3, 0, 12, 12, 4);
arm64_vgic_sys_reg!(SYS_ICC_IGRPEN0_EL1, 3, 0, 12, 12, 6);
arm64_vgic_sys_reg!(SYS_ICC_IGRPEN1_EL1, 3, 0, 12, 12, 7);
arm64_vgic_sys_reg!(SYS_ICC_PMR_EL1, 3, 0, 4, 6, 0);
arm64_vgic_sys_reg!(SYS_ICC_BPR0_EL1, 3, 0, 12, 8, 3);
arm64_vgic_sys_reg!(SYS_ICC_BPR1_EL1, 3, 0, 12, 12, 3);
SYS_ICC_AP0Rn_EL1!(SYS_ICC_AP0R0_EL1, 0);
SYS_ICC_AP0Rn_EL1!(SYS_ICC_AP0R1_EL1, 1);
SYS_ICC_AP0Rn_EL1!(SYS_ICC_AP0R2_EL1, 2);
SYS_ICC_AP0Rn_EL1!(SYS_ICC_AP0R3_EL1, 3);
SYS_ICC_AP1Rn_EL1!(SYS_ICC_AP1R0_EL1, 0);
SYS_ICC_AP1Rn_EL1!(SYS_ICC_AP1R1_EL1, 1);
SYS_ICC_AP1Rn_EL1!(SYS_ICC_AP1R2_EL1, 2);
SYS_ICC_AP1Rn_EL1!(SYS_ICC_AP1R3_EL1, 3);
static VGIC_ICC_REGS: &'static [u64] = &[
SYS_ICC_SRE_EL1,
SYS_ICC_CTLR_EL1,
SYS_ICC_IGRPEN0_EL1,
SYS_ICC_IGRPEN1_EL1,
SYS_ICC_PMR_EL1,
SYS_ICC_BPR0_EL1,
SYS_ICC_BPR1_EL1,
SYS_ICC_AP0R0_EL1,
SYS_ICC_AP0R1_EL1,
SYS_ICC_AP0R2_EL1,
SYS_ICC_AP0R3_EL1,
SYS_ICC_AP1R0_EL1,
SYS_ICC_AP1R1_EL1,
SYS_ICC_AP1R2_EL1,
SYS_ICC_AP1R3_EL1,
];
fn icc_attr_access(
gic: &Arc<dyn hypervisor::Device>,
offset: u64,
typer: u64,
val: &u32,
set: bool,
) -> Result<()> {
let mut gic_icc_attr = kvm_device_attr {
group: KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
attr: ((typer & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) | offset), // this needs the mpidr
addr: val as *const u32 as u64,
flags: 0,
};
if set {
#[allow(clippy::unnecessary_mut_passed)]
gic.set_device_attr(&mut gic_icc_attr)
.map_err(Error::SetDeviceAttribute)?;
} else {
gic.get_device_attr(&mut gic_icc_attr)
.map_err(Error::GetDeviceAttribute)?;
}
Ok(())
}
/// Get ICC registers.
pub fn get_icc_regs(gic: &Arc<dyn hypervisor::Device>, gicr_typer: &[u64]) -> Result<Vec<u32>> {
let mut state: Vec<u32> = Vec::new();
// We need this for the ICC_AP<m>R<n>_EL1 registers.
let mut num_priority_bits = 0;
for ix in gicr_typer {
let i = *ix;
for icc_offset in VGIC_ICC_REGS {
let val = 0;
if *icc_offset == SYS_ICC_CTLR_EL1 {
// calculate priority bits by reading the ctrl_el1 register.
icc_attr_access(gic, *icc_offset, i, &val, false)?;
// The priority bits are found in the ICC_CTLR_EL1 register (bits from 10:8).
// See page 194 from https://static.docs.arm.com/ihi0069/c/IHI0069C_gic_
// architecture_specification.pdf.
// Citation:
// "Priority bits. Read-only and writes are ignored. The number of priority bits
// implemented, minus one."
num_priority_bits =
((val & ICC_CTLR_EL1_PRIBITS_MASK) >> ICC_CTLR_EL1_PRIBITS_SHIFT) + 1;
state.push(val);
}
// As per ARMv8 documentation: https://static.docs.arm.com/ihi0069/c/IHI0069C_
// gic_architecture_specification.pdf
// page 178,
// ICC_AP0R1_EL1 is only implemented in implementations that support 6 or more bits of
// priority.
// ICC_AP0R2_EL1 and ICC_AP0R3_EL1 are only implemented in implementations that support
// 7 bits of priority.
else if *icc_offset == SYS_ICC_AP0R1_EL1 || *icc_offset == SYS_ICC_AP1R1_EL1 {
if num_priority_bits >= 6 {
icc_attr_access(gic, *icc_offset, i, &val, false)?;
state.push(val);
}
} else if *icc_offset == SYS_ICC_AP0R2_EL1
|| *icc_offset == SYS_ICC_AP0R3_EL1
|| *icc_offset == SYS_ICC_AP1R2_EL1
|| *icc_offset == SYS_ICC_AP1R3_EL1
{
if num_priority_bits == 7 {
icc_attr_access(gic, *icc_offset, i, &val, false)?;
state.push(val);
}
} else {
icc_attr_access(gic, *icc_offset, i, &val, false)?;
state.push(val);
}
}
}
Ok(state)
}
/// Set ICC registers.
pub fn set_icc_regs(
gic: &Arc<dyn hypervisor::Device>,
gicr_typer: &[u64],
state: &[u32],
) -> Result<()> {
let mut num_priority_bits = 0;
let mut idx = 0;
for ix in gicr_typer {
let i = *ix;
for icc_offset in VGIC_ICC_REGS {
if *icc_offset == SYS_ICC_CTLR_EL1 {
let ctrl_el1 = state[idx];
num_priority_bits =
((ctrl_el1 & ICC_CTLR_EL1_PRIBITS_MASK) >> ICC_CTLR_EL1_PRIBITS_SHIFT) + 1;
}
if *icc_offset == SYS_ICC_AP0R1_EL1 || *icc_offset == SYS_ICC_AP1R1_EL1 {
if num_priority_bits >= 6 {
icc_attr_access(gic, *icc_offset, i, &state[idx], true)?;
idx += 1;
}
continue;
}
if *icc_offset == SYS_ICC_AP0R2_EL1
|| *icc_offset == SYS_ICC_AP0R3_EL1
|| *icc_offset == SYS_ICC_AP1R2_EL1
|| *icc_offset == SYS_ICC_AP1R3_EL1
{
if num_priority_bits == 7 {
icc_attr_access(gic, *icc_offset, i, &state[idx], true)?;
idx += 1;
}
continue;
}
icc_attr_access(gic, *icc_offset, i, &state[idx], true)?;
idx += 1;
}
}
Ok(())
}

211
arch/src/aarch64/gic/mod.rs Normal file
View File

@@ -0,0 +1,211 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
pub mod dist_regs;
pub mod gicv3;
pub mod gicv3_its;
pub mod icc_regs;
pub mod redist_regs;
pub use self::dist_regs::{get_dist_regs, read_ctlr, set_dist_regs, write_ctlr};
pub use self::icc_regs::{get_icc_regs, set_icc_regs};
pub use self::redist_regs::{get_redist_regs, set_redist_regs};
use std::any::Any;
use std::result;
use std::sync::Arc;
/// Errors thrown while setting up the GIC.
#[derive(Debug)]
pub enum Error {
/// Error while calling KVM ioctl for setting up the global interrupt controller.
CreateGic(hypervisor::HypervisorVmError),
/// Error while setting device attributes for the GIC.
SetDeviceAttribute(hypervisor::HypervisorDeviceError),
/// Error while getting device attributes for the GIC.
GetDeviceAttribute(hypervisor::HypervisorDeviceError),
}
type Result<T> = result::Result<T, Error>;
pub trait GicDevice: Send {
/// Returns the hypervisor agnostic Device of the GIC device
fn device(&self) -> &Arc<dyn hypervisor::Device>;
/// Returns the fdt compatibility property of the device
fn fdt_compatibility(&self) -> &str;
/// Returns the maint_irq fdt property of the device
fn fdt_maint_irq(&self) -> u32;
/// Returns an array with GIC device properties
fn device_properties(&self) -> &[u64];
/// Returns the number of vCPUs this GIC handles
fn vcpu_count(&self) -> u64;
/// Returns whether the GIC device is MSI compatible or not
fn msi_compatible(&self) -> bool {
false
}
/// Returns the MSI compatibility property of the device
fn msi_compatibility(&self) -> &str {
""
}
/// Returns the MSI reg property of the device
fn msi_properties(&self) -> &[u64] {
&[]
}
/// Get the values of GICR_TYPER for each vCPU.
fn set_gicr_typers(&mut self, gicr_typers: Vec<u64>);
/// Downcast the trait object to its concrete type.
fn as_any_concrete_mut(&mut self) -> &mut dyn Any;
}
pub mod kvm {
use super::GicDevice;
use super::Result;
use crate::aarch64::gic::gicv3_its::kvm::KvmGicV3Its;
use crate::layout;
use hypervisor::kvm::kvm_bindings;
use std::boxed::Box;
use std::sync::Arc;
/// Trait for GIC devices.
pub trait KvmGicDevice: Send + Sync + GicDevice {
/// Returns the GIC version of the device
fn version() -> u32;
/// Create the GIC device object
fn create_device(
device: Arc<dyn hypervisor::Device>,
vcpu_count: u64,
) -> Box<dyn GicDevice>;
/// Setup the device-specific attributes
fn init_device_attributes(
vm: &Arc<dyn hypervisor::Vm>,
gic_device: &dyn GicDevice,
) -> Result<()>;
/// Initialize a GIC device
fn init_device(vm: &Arc<dyn hypervisor::Vm>) -> Result<Arc<dyn hypervisor::Device>> {
let mut gic_device = kvm_bindings::kvm_create_device {
type_: Self::version(),
fd: 0,
flags: 0,
};
vm.create_device(&mut gic_device)
.map_err(super::Error::CreateGic)
}
/// Set a GIC device attribute
fn set_device_attribute(
device: &Arc<dyn hypervisor::Device>,
group: u32,
attr: u64,
addr: u64,
flags: u32,
) -> Result<()> {
let attr = kvm_bindings::kvm_device_attr {
group,
attr,
addr,
flags,
};
device
.set_device_attr(&attr)
.map_err(super::Error::SetDeviceAttribute)?;
Ok(())
}
/// Get a GIC device attribute
fn get_device_attribute(
device: &Arc<dyn hypervisor::Device>,
group: u32,
attr: u64,
addr: u64,
flags: u32,
) -> Result<()> {
let mut attr = kvm_bindings::kvm_device_attr {
group,
attr,
addr,
flags,
};
device
.get_device_attr(&mut attr)
.map_err(super::Error::GetDeviceAttribute)?;
Ok(())
}
/// Finalize the setup of a GIC device
fn finalize_device(gic_device: &dyn GicDevice) -> Result<()> {
/* We need to tell the kernel how many irqs to support with this vgic.
* See the `layout` module for details.
*/
let nr_irqs: u32 = layout::IRQ_MAX - layout::IRQ_BASE + 1;
let nr_irqs_ptr = &nr_irqs as *const u32;
Self::set_device_attribute(
gic_device.device(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
0,
nr_irqs_ptr as u64,
0,
)?;
/* Finalize the GIC.
* See https://code.woboq.org/linux/linux/virt/kvm/arm/vgic/vgic-kvm-device.c.html#211.
*/
Self::set_device_attribute(
gic_device.device(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_CTRL,
u64::from(kvm_bindings::KVM_DEV_ARM_VGIC_CTRL_INIT),
0,
0,
)?;
Ok(())
}
/// Method to initialize the GIC device
#[allow(clippy::new_ret_no_self)]
fn new(vm: &Arc<dyn hypervisor::Vm>, vcpu_count: u64) -> Result<Box<dyn GicDevice>> {
let vgic_fd = Self::init_device(vm)?;
let device = Self::create_device(vgic_fd, vcpu_count);
Self::init_device_attributes(vm, &*device)?;
Self::finalize_device(&*device)?;
Ok(device)
}
}
/// Create a GICv3-ITS device.
///
pub fn create_gic(vm: &Arc<dyn hypervisor::Vm>, vcpu_count: u64) -> Result<Box<dyn GicDevice>> {
debug!("creating a GICv3-ITS");
KvmGicV3Its::new(vm, vcpu_count)
}
/// Function that saves RDIST pending tables into guest RAM.
///
/// The tables get flushed to guest RAM whenever the VM gets stopped.
pub fn save_pending_tables(gic: &Arc<dyn hypervisor::Device>) -> Result<()> {
let init_gic_attr = kvm_bindings::kvm_device_attr {
group: kvm_bindings::KVM_DEV_ARM_VGIC_GRP_CTRL,
attr: u64::from(kvm_bindings::KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES),
addr: 0,
flags: 0,
};
gic.set_device_attr(&init_gic_attr)
.map_err(super::Error::SetDeviceAttribute)
}
}

View File

@@ -0,0 +1,179 @@
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use super::{Error, Result};
use hypervisor::kvm::kvm_bindings::{kvm_device_attr, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS};
use std::sync::Arc;
// Relevant redistributor registers that we want to save/restore.
const GICR_CTLR: u32 = 0x0000;
const GICR_STATUSR: u32 = 0x0010;
const GICR_WAKER: u32 = 0x0014;
const GICR_PROPBASER: u32 = 0x0070;
const GICR_PENDBASER: u32 = 0x0078;
/* SGI and PPI Redistributor registers, offsets from RD_base */
/*
* Redistributor frame offsets from RD_base which is actually SZ_
*/
const GICR_SGI_OFFSET: u32 = 0x0001_0000;
const GICR_IGROUPR0: u32 = GICR_SGI_OFFSET + 0x0080;
const GICR_ICENABLER0: u32 = GICR_SGI_OFFSET + 0x0180;
const GICR_ISENABLER0: u32 = GICR_SGI_OFFSET + 0x0100;
const GICR_ISPENDR0: u32 = GICR_SGI_OFFSET + 0x0200;
const GICR_ICPENDR0: u32 = GICR_SGI_OFFSET + 0x0280;
const GICR_ISACTIVER0: u32 = GICR_SGI_OFFSET + 0x0300;
const GICR_ICACTIVER0: u32 = GICR_SGI_OFFSET + 0x0380;
const GICR_IPRIORITYR0: u32 = GICR_SGI_OFFSET + 0x0400;
const GICR_ICFGR0: u32 = GICR_SGI_OFFSET + 0x0C00;
const KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT: u32 = 32;
const KVM_DEV_ARM_VGIC_V3_MPIDR_MASK: u64 = 0xffffffff << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT as u64;
/// This is how we represent the registers of a distributor.
/// It is relrvant their offset from the base address of the
/// distributor.
/// Each register has a different number
/// of bits_per_irq and is therefore variable length.
/// First 32 interrupts (0-32) are private to each CPU (SGIs and PPIs).
/// and so we save the first irq to identify between the type of the interrupt
/// that the respective register deals with.
struct RdistReg {
/// Offset from distributor address.
base: u32,
/// Length of the register.
length: u8,
}
// All or at least the registers we are interested in are 32 bit, so
// we use a constant for size(u32).
const REG_SIZE: u8 = 4;
// Creates a vgic redistributor register.
macro_rules! VGIC_RDIST_REG {
($base:expr, $len:expr) => {
RdistReg {
base: $base,
length: $len,
}
};
}
// List with relevant distributor registers that we will be restoring.
static VGIC_RDIST_REGS: &'static [RdistReg] = &[
VGIC_RDIST_REG!(GICR_CTLR, 4),
VGIC_RDIST_REG!(GICR_STATUSR, 4),
VGIC_RDIST_REG!(GICR_WAKER, 4),
VGIC_RDIST_REG!(GICR_PROPBASER, 8),
VGIC_RDIST_REG!(GICR_PENDBASER, 8),
];
// List with relevant distributor registers that we will be restoring.
static VGIC_SGI_REGS: &'static [RdistReg] = &[
VGIC_RDIST_REG!(GICR_IGROUPR0, 4),
VGIC_RDIST_REG!(GICR_ICENABLER0, 4),
VGIC_RDIST_REG!(GICR_ISENABLER0, 4),
VGIC_RDIST_REG!(GICR_ICFGR0, 8),
VGIC_RDIST_REG!(GICR_ICPENDR0, 4),
VGIC_RDIST_REG!(GICR_ISPENDR0, 4),
VGIC_RDIST_REG!(GICR_ICACTIVER0, 4),
VGIC_RDIST_REG!(GICR_ISACTIVER0, 4),
VGIC_RDIST_REG!(GICR_IPRIORITYR0, 32),
];
fn redist_attr_access(
gic: &Arc<dyn hypervisor::Device>,
offset: u32,
typer: u64,
val: &u32,
set: bool,
) -> Result<()> {
let mut gic_dist_attr = kvm_device_attr {
group: KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
attr: (typer & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) | (offset as u64), // this needs the mpidr
addr: val as *const u32 as u64,
flags: 0,
};
if set {
#[allow(clippy::unnecessary_mut_passed)]
gic.set_device_attr(&mut gic_dist_attr)
.map_err(Error::SetDeviceAttribute)?;
} else {
gic.get_device_attr(&mut gic_dist_attr)
.map_err(Error::GetDeviceAttribute)?;
}
Ok(())
}
fn access_redists_aux(
gic: &Arc<dyn hypervisor::Device>,
gicr_typer: &[u64],
state: &mut Vec<u32>,
reg_list: &'static [RdistReg],
idx: &mut usize,
set: bool,
) -> Result<()> {
for i in gicr_typer {
for rdreg in reg_list {
let mut base = rdreg.base;
let end = base + rdreg.length as u32;
while base < end {
let mut val = 0;
if set {
val = state[*idx];
redist_attr_access(gic, base, *i, &val, true)?;
*idx += 1;
} else {
redist_attr_access(gic, base, *i, &val, false)?;
state.push(val);
}
base += REG_SIZE as u32;
}
}
}
Ok(())
}
/// Get redistributor registers.
pub fn get_redist_regs(gic: &Arc<dyn hypervisor::Device>, gicr_typer: &[u64]) -> Result<Vec<u32>> {
let mut state = Vec::new();
let mut idx: usize = 0;
access_redists_aux(
gic,
&gicr_typer,
&mut state,
VGIC_RDIST_REGS,
&mut idx,
false,
)?;
access_redists_aux(gic, &gicr_typer, &mut state, VGIC_SGI_REGS, &mut idx, false)?;
Ok(state)
}
/// Set redistributor registers.
pub fn set_redist_regs(
gic: &Arc<dyn hypervisor::Device>,
gicr_typer: &[u64],
state: &[u32],
) -> Result<()> {
let mut idx: usize = 0;
let mut mut_state = state.to_owned();
access_redists_aux(
gic,
gicr_typer,
&mut mut_state,
VGIC_RDIST_REGS,
&mut idx,
true,
)?;
access_redists_aux(
gic,
gicr_typer,
&mut mut_state,
VGIC_SGI_REGS,
&mut idx,
true,
)
}

View File

@@ -1,114 +0,0 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use std::{boxed::Box, result};
use kvm_ioctls::DeviceFd;
use super::gic::{Error, GICDevice};
type Result<T> = result::Result<T, Error>;
/// Represent a GIC v2 device
pub struct GICv2 {
/// The file descriptor for the KVM device
fd: DeviceFd,
/// GIC device properties, to be used for setting up the fdt entry
properties: [u64; 4],
/// Number of CPUs handled by the device
vcpu_count: u64,
}
impl GICv2 {
// Unfortunately bindgen omits defines that are based on other defines.
// See arch/arm64/include/uapi/asm/kvm.h file from the linux kernel.
const KVM_VGIC_V2_DIST_SIZE: u64 = 0x1000;
const KVM_VGIC_V2_CPU_SIZE: u64 = 0x2000;
// Device trees specific constants
const ARCH_GIC_V2_MAINT_IRQ: u32 = 8;
/// Get the address of the GICv2 distributor.
const fn get_dist_addr() -> u64 {
super::layout::MAPPED_IO_START - GICv2::KVM_VGIC_V2_DIST_SIZE
}
/// Get the size of the GIC_v2 distributor.
const fn get_dist_size() -> u64 {
GICv2::KVM_VGIC_V2_DIST_SIZE
}
/// Get the address of the GIC_v2 CPU.
const fn get_cpu_addr() -> u64 {
GICv2::get_dist_addr() - GICv2::KVM_VGIC_V2_CPU_SIZE
}
/// Get the size of the GIC_v2 CPU.
const fn get_cpu_size() -> u64 {
GICv2::KVM_VGIC_V2_CPU_SIZE
}
}
impl GICDevice for GICv2 {
fn version() -> u32 {
kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2
}
fn device_fd(&self) -> &DeviceFd {
&self.fd
}
fn device_properties(&self) -> &[u64] {
&self.properties
}
fn vcpu_count(&self) -> u64 {
self.vcpu_count
}
fn fdt_compatibility(&self) -> &str {
"arm,gic-400"
}
fn fdt_maint_irq(&self) -> u32 {
GICv2::ARCH_GIC_V2_MAINT_IRQ
}
fn create_device(fd: DeviceFd, vcpu_count: u64) -> Box<dyn GICDevice> {
Box::new(GICv2 {
fd: fd,
properties: [
GICv2::get_dist_addr(),
GICv2::get_dist_size(),
GICv2::get_cpu_addr(),
GICv2::get_cpu_size(),
],
vcpu_count: vcpu_count,
})
}
fn init_device_attributes(gic_device: &Box<dyn GICDevice>) -> Result<()> {
/* Setting up the distributor attribute.
We are placing the GIC below 1GB so we need to substract the size of the distributor. */
Self::set_device_attribute(
&gic_device.device_fd(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
u64::from(kvm_bindings::KVM_VGIC_V2_ADDR_TYPE_DIST),
&GICv2::get_dist_addr() as *const u64 as u64,
0,
)?;
/* Setting up the CPU attribute. */
Self::set_device_attribute(
&gic_device.device_fd(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
u64::from(kvm_bindings::KVM_VGIC_V2_ADDR_TYPE_CPU),
&GICv2::get_cpu_addr() as *const u64 as u64,
0,
)?;
Ok(())
}
}

View File

@@ -1,117 +0,0 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use std::{boxed::Box, result};
use kvm_ioctls::DeviceFd;
use super::gic::{Error, GICDevice};
type Result<T> = result::Result<T, Error>;
pub struct GICv3 {
/// The file descriptor for the KVM device
fd: DeviceFd,
/// GIC device properties, to be used for setting up the fdt entry
properties: [u64; 4],
/// Number of CPUs handled by the device
vcpu_count: u64,
}
impl GICv3 {
// Unfortunately bindgen omits defines that are based on other defines.
// See arch/arm64/include/uapi/asm/kvm.h file from the linux kernel.
const SZ_64K: u64 = 0x0001_0000;
const KVM_VGIC_V3_DIST_SIZE: u64 = GICv3::SZ_64K;
const KVM_VGIC_V3_REDIST_SIZE: u64 = (2 * GICv3::SZ_64K);
// Device trees specific constants
const ARCH_GIC_V3_MAINT_IRQ: u32 = 9;
/// Get the address of the GIC distributor.
fn get_dist_addr() -> u64 {
super::layout::MAPPED_IO_START - GICv3::KVM_VGIC_V3_DIST_SIZE
}
/// Get the size of the GIC distributor.
fn get_dist_size() -> u64 {
GICv3::KVM_VGIC_V3_DIST_SIZE
}
/// Get the address of the GIC redistributors.
fn get_redists_addr(vcpu_count: u64) -> u64 {
GICv3::get_dist_addr() - GICv3::get_redists_size(vcpu_count)
}
/// Get the size of the GIC redistributors.
fn get_redists_size(vcpu_count: u64) -> u64 {
vcpu_count * GICv3::KVM_VGIC_V3_REDIST_SIZE
}
}
impl GICDevice for GICv3 {
fn version() -> u32 {
kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3
}
fn device_fd(&self) -> &DeviceFd {
&self.fd
}
fn device_properties(&self) -> &[u64] {
&self.properties
}
fn vcpu_count(&self) -> u64 {
self.vcpu_count
}
fn fdt_compatibility(&self) -> &str {
"arm,gic-v3"
}
fn fdt_maint_irq(&self) -> u32 {
GICv3::ARCH_GIC_V3_MAINT_IRQ
}
fn create_device(fd: DeviceFd, vcpu_count: u64) -> Box<dyn GICDevice> {
Box::new(GICv3 {
fd: fd,
properties: [
GICv3::get_dist_addr(),
GICv3::get_dist_size(),
GICv3::get_redists_addr(vcpu_count),
GICv3::get_redists_size(vcpu_count),
],
vcpu_count: vcpu_count,
})
}
fn init_device_attributes(gic_device: &Box<dyn GICDevice>) -> Result<()> {
/* Setting up the distributor attribute.
We are placing the GIC below 1GB so we need to substract the size of the distributor.
*/
Self::set_device_attribute(
&gic_device.device_fd(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_DIST),
&GICv3::get_dist_addr() as *const u64 as u64,
0,
)?;
/* Setting up the redistributors' attribute.
We are calculating here the start of the redistributors address. We have one per CPU.
*/
Self::set_device_attribute(
&gic_device.device_fd(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_REDIST),
&GICv3::get_redists_addr(u64::from(gic_device.vcpu_count())) as *const u64 as u64,
0,
)?;
Ok(())
}
}

View File

@@ -37,13 +37,13 @@
// | |
// 144 M +---------------------------------------------------------------|
// | |
// | Reserverd (now GIC is here) |
// | Reserved (now GIC is here) |
// | |
// 0GB +---------------------------------------------------------------+
//
//
use vm_memory::{GuestAddress, GuestUsize};
use vm_memory::GuestAddress;
/// Below this address will reside the GIC, above this address will reside the MMIO devices.
pub const MAPPED_IO_START: u64 = 0x0900_0000;
@@ -51,6 +51,7 @@ pub const MAPPED_IO_START: u64 = 0x0900_0000;
/// Space 0x0900_0000 ~ 0x1000_0000 is reserved for legacy devices.
pub const LEGACY_SERIAL_MAPPED_IO_START: u64 = 0x0900_0000;
pub const LEGACY_RTC_MAPPED_IO_START: u64 = 0x0901_0000;
pub const LEGACY_GPIO_MAPPED_IO_START: u64 = 0x0902_0000;
/// Legacy space will be allocated at once whiling setting up legacy devices.
pub const LEGACY_DEVICES_MAPPED_IO_SIZE: u64 = 0x0700_0000;
@@ -61,7 +62,7 @@ pub const MEM_32BIT_DEVICES_SIZE: u64 = 0x3000_0000;
/// PCI MMCONFIG space (start: after the device space at 1 GiB, length: 256MiB)
pub const PCI_MMCONFIG_START: GuestAddress = GuestAddress(0x4000_0000);
pub const PCI_MMCONFIG_SIZE: GuestUsize = 256 << 20;
pub const PCI_MMCONFIG_SIZE: u64 = 256 << 20;
/// Start of RAM on 64 bit ARM.
pub const RAM_64BIT_START: u64 = 0x8000_0000;
@@ -78,9 +79,9 @@ pub const FDT_MAX_SIZE: usize = 0x20_0000;
// * bigger than 32
// * less than 1023 and
// * a multiple of 32.
// We are setting up our interrupt controller to support a maximum of 128 interrupts.
// We are setting up our interrupt controller to support a maximum of 256 interrupts.
/// First usable interrupt on aarch64.
pub const IRQ_BASE: u32 = 32;
pub const IRQ_BASE: u32 = 0;
/// Last usable interrupt on aarch64.
pub const IRQ_MAX: u32 = 159;
pub const IRQ_MAX: u32 = 255;

View File

@@ -6,20 +6,19 @@
pub mod fdt;
/// Module for the global interrupt controller configuration.
pub mod gic;
mod gicv2;
mod gicv3;
/// Layout for this aarch64 system.
pub mod layout;
/// Logic for configuring aarch64 registers.
pub mod regs;
pub use self::fdt::DeviceInfoForFDT;
pub use self::fdt::DeviceInfoForFdt;
use crate::DeviceType;
use crate::RegionType;
use kvm_ioctls::*;
use aarch64::gic::GicDevice;
use std::collections::HashMap;
use std::ffi::CStr;
use std::fmt::Debug;
use std::sync::Arc;
use vm_memory::{
Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, GuestMemoryMmap,
GuestUsize,
@@ -29,22 +28,19 @@ use vm_memory::{
#[derive(Debug)]
pub enum Error {
/// Failed to create a FDT.
SetupFDT(fdt::Error),
SetupFdt(fdt::Error),
/// Failed to create a GIC.
SetupGIC(gic::Error),
SetupGic(gic::Error),
/// Failed to compute the initrd address.
InitrdAddress,
/// Failed to compute the initramfs address.
InitramfsAddress,
/// Error configuring the general purpose registers
REGSConfiguration(regs::Error),
RegsConfiguration(regs::Error),
/// Error fetching prefered target
VcpuArmPreferredTarget(kvm_ioctls::Error),
/// Error doing Vcpu Init on Arm.
VcpuArmInit(kvm_ioctls::Error),
/// Error configuring the MPIDR register
VcpuRegMpidr(hypervisor::HypervisorCpuError),
}
impl From<Error> for super::Error {
@@ -63,26 +59,11 @@ pub struct EntryPoint {
/// Configure the specified VCPU, and return its MPIDR.
pub fn configure_vcpu(
fd: &VcpuFd,
fd: &Arc<dyn hypervisor::Vcpu>,
id: u8,
vm_fd: &VmFd,
kernel_entry_point: Option<EntryPoint>,
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
) -> super::Result<u64> {
let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default();
// This reads back the kernel's preferred target type.
vm_fd
.get_preferred_target(&mut kvi)
.map_err(Error::VcpuArmPreferredTarget)?;
// We already checked that the capability is supported.
kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_PSCI_0_2;
// Non-boot cpus are powered off initially.
if id > 0 {
kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_POWER_OFF;
}
fd.vcpu_init(&kvi).map_err(Error::VcpuArmInit)?;
if let Some(kernel_entry_point) = kernel_entry_point {
regs::setup_regs(
fd,
@@ -90,43 +71,39 @@ pub fn configure_vcpu(
kernel_entry_point.entry_addr.raw_value(),
&vm_memory.memory(),
)
.map_err(Error::REGSConfiguration)?;
.map_err(Error::RegsConfiguration)?;
}
let mpidr = regs::read_mpidr(fd).map_err(Error::REGSConfiguration)?;
let mpidr = fd.read_mpidr().map_err(Error::VcpuRegMpidr)?;
Ok(mpidr)
}
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
let mut regions = Vec::new();
// 0 ~ 256 MiB: Reserved
regions.push((
GuestAddress(0),
layout::MEM_32BIT_DEVICES_START.0 as usize,
RegionType::Reserved,
));
// 256 MiB ~ 1 G: MMIO space
regions.push((
layout::MEM_32BIT_DEVICES_START,
layout::MEM_32BIT_DEVICES_SIZE as usize,
RegionType::SubRegion,
));
// 1G ~ 2G: reserved. The leading 256M for PCIe MMCONFIG space
regions.push((
layout::PCI_MMCONFIG_START,
(layout::RAM_64BIT_START - layout::PCI_MMCONFIG_START.0) as usize,
RegionType::Reserved,
));
regions.push((
GuestAddress(layout::RAM_64BIT_START),
size as usize,
RegionType::Ram,
));
regions
vec![
// 0 ~ 256 MiB: Reserved
(
GuestAddress(0),
layout::MEM_32BIT_DEVICES_START.0 as usize,
RegionType::Reserved,
),
// 256 MiB ~ 1 G: MMIO space
(
layout::MEM_32BIT_DEVICES_START,
layout::MEM_32BIT_DEVICES_SIZE as usize,
RegionType::SubRegion,
),
// 1G ~ 2G: reserved. The leading 256M for PCIe MMCONFIG space
(
layout::PCI_MMCONFIG_START,
(layout::RAM_64BIT_START - layout::PCI_MMCONFIG_START.0) as usize,
RegionType::Reserved,
),
(
GuestAddress(layout::RAM_64BIT_START),
size as usize,
RegionType::Ram,
),
]
}
/// Configures the system and should be called once per vm before starting vcpu threads.
@@ -136,29 +113,50 @@ pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, Region
/// * `guest_mem` - The memory to be used by the guest.
/// * `num_cpus` - Number of virtual CPUs the guest will have.
#[allow(clippy::too_many_arguments)]
#[allow(unused_variables)]
pub fn configure_system<T: DeviceInfoForFDT + Clone + Debug>(
vm_fd: &VmFd,
pub fn configure_system<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
vm: &Arc<dyn hypervisor::Vm>,
guest_mem: &GuestMemoryMmap,
cmdline_cstring: &CStr,
vcpu_count: u64,
vcpu_mpidr: Vec<u64>,
device_info: &HashMap<(DeviceType, String), T>,
device_info: &HashMap<(DeviceType, String), T, S>,
initrd: &Option<super::InitramfsConfig>,
) -> super::Result<()> {
let gic_device = gic::create_gic(vm_fd, vcpu_count).map_err(Error::SetupGIC)?;
pci_space_address: &(u64, u64),
) -> super::Result<Box<dyn GicDevice>> {
let gic_device = gic::kvm::create_gic(vm, vcpu_count).map_err(Error::SetupGic)?;
let dtb = fdt::create_fdt(
fdt::create_fdt(
guest_mem,
cmdline_cstring,
vcpu_mpidr,
device_info,
&gic_device,
&*gic_device,
initrd,
pci_space_address,
)
.map_err(Error::SetupFDT)?;
.map_err(Error::SetupFdt)?;
Ok(())
Ok(gic_device)
}
/// Returns the memory address where the initramfs could be loaded.
pub fn initramfs_load_addr(
guest_mem: &GuestMemoryMmap,
initramfs_size: usize,
) -> super::Result<u64> {
let round_to_pagesize = |size| (size + (super::PAGE_SIZE - 1)) & !(super::PAGE_SIZE - 1);
match GuestAddress(get_fdt_addr(&guest_mem))
.checked_sub(round_to_pagesize(initramfs_size) as u64)
{
Some(offset) => {
if guest_mem.address_in_range(offset) {
Ok(offset.raw_value())
} else {
Err(super::Error::AArch64Setup(Error::InitramfsAddress))
}
}
None => Err(super::Error::AArch64Setup(Error::InitramfsAddress)),
}
}
/// Returns the memory address where the kernel could be loaded.
@@ -184,10 +182,10 @@ fn get_fdt_addr(mem: &GuestMemoryMmap) -> u64 {
pub fn get_host_cpu_phys_bits() -> u8 {
// The value returned here is used to determine the physical address space size
// for a VM (IPA size).
// In recent kernel versions, the maxium IPA size supported by the host can be
// In recent kernel versions, the maximum IPA size supported by the host can be
// known by querying cap KVM_CAP_ARM_VM_IPA_SIZE. And the IPA size for a
// guest can be configured smaller.
// But in Cloud-Hypervisor we simply use the maxium value for the VM.
// But in Cloud-Hypervisor we simply use the maximum value for the VM.
// Reference https://lwn.net/Articles/766767/.
//
// The correct way to query KVM_CAP_ARM_VM_IPA_SIZE is via rust-vmm/kvm-ioctls,
@@ -200,13 +198,6 @@ pub fn get_host_cpu_phys_bits() -> u8 {
40
}
pub fn check_required_kvm_extensions(kvm: &Kvm) -> super::Result<()> {
if !kvm.check_extension(Cap::SignalMsi) {
return Err(super::Error::CapabilityMissing(Cap::SignalMsi));
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -5,27 +5,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.
use std::{mem, result};
use super::get_fdt_addr;
use kvm_bindings::{
user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG, KVM_REG_ARM64_SYSREG_CRM_MASK,
KVM_REG_ARM64_SYSREG_CRM_SHIFT, KVM_REG_ARM64_SYSREG_CRN_MASK, KVM_REG_ARM64_SYSREG_CRN_SHIFT,
KVM_REG_ARM64_SYSREG_OP0_MASK, KVM_REG_ARM64_SYSREG_OP0_SHIFT, KVM_REG_ARM64_SYSREG_OP1_MASK,
KVM_REG_ARM64_SYSREG_OP1_SHIFT, KVM_REG_ARM64_SYSREG_OP2_MASK, KVM_REG_ARM64_SYSREG_OP2_SHIFT,
KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
use hypervisor::kvm::kvm_bindings::{
kvm_regs, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
};
use kvm_ioctls::VcpuFd;
use hypervisor::{arm64_core_reg_id, offset__of};
use std::sync::Arc;
use std::{mem, result};
use vm_memory::GuestMemoryMmap;
/// Errors thrown while setting aarch64 registers.
#[derive(Debug)]
pub enum Error {
/// Failed to set core register (PC, PSTATE or general purpose ones).
SetCoreRegister(kvm_ioctls::Error),
SetCoreRegister(hypervisor::HypervisorCpuError),
/// Failed to get a system register.
GetSysRegister(kvm_ioctls::Error),
GetSysRegister(hypervisor::HypervisorCpuError),
}
type Result<T> = result::Result<T, Error>;
@@ -40,80 +35,6 @@ const PSR_D_BIT: u64 = 0x0000_0200;
// Taken from arch/arm64/kvm/inject_fault.c.
const PSTATE_FAULT_BITS_64: u64 = PSR_MODE_EL1h | PSR_A_BIT | PSR_F_BIT | PSR_I_BIT | PSR_D_BIT;
// Following are macros that help with getting the ID of a aarch64 core register.
// The core register are represented by the user_pt_regs structure. Look for it in
// arch/arm64/include/uapi/asm/ptrace.h.
// This macro gets the offset of a structure (i.e `str`) member (i.e `field`) without having
// an instance of that structure.
// It uses a null pointer to retrieve the offset to the field.
// Inspired by C solution: `#define offsetof(str, f) ((size_t)(&((str *)0)->f))`.
// Doing `offset__of!(user_pt_regs, pstate)` in our rust code will trigger the following:
// unsafe { &(*(0 as *const user_pt_regs)).pstate as *const _ as usize }
// The dereference expression produces an lvalue, but that lvalue is not actually read from,
// we're just doing pointer math on it, so in theory, it should safe.
macro_rules! offset__of {
($str:ty, $field:ident) => {
unsafe { &(*(0 as *const $str)).$field as *const _ as usize }
};
}
macro_rules! arm64_core_reg {
($reg: tt) => {
// As per `kvm_arm_copy_reg_indices`, the id of a core register can be obtained like this:
// `const u64 core_reg = KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | i`, where i is obtained with:
// `for (i = 0; i < sizeof(struct kvm_regs) / sizeof(__u32); i++) {`
// We are using here `user_pt_regs` since this structure contains the core register and it is at
// the start of `kvm_regs`.
// struct kvm_regs {
// struct user_pt_regs regs; /* sp = sp_el0 */
//
// __u64 sp_el1;
// __u64 elr_el1;
//
// __u64 spsr[KVM_NR_SPSR];
//
// struct user_fpsimd_state fp_regs;
//};
// struct user_pt_regs {
// __u64 regs[31];
// __u64 sp;
// __u64 pc;
// __u64 pstate;
//};
// In our implementation we need: pc, pstate and user_pt_regs->regs[0].
KVM_REG_ARM64 as u64
| KVM_REG_SIZE_U64 as u64
| u64::from(KVM_REG_ARM_CORE)
| ((offset__of!(user_pt_regs, $reg) / mem::size_of::<u32>()) as u64)
};
}
// This macro computes the ID of a specific ARM64 system register similar to how
// the kernel C macro does.
// https://elixir.bootlin.com/linux/v4.20.17/source/arch/arm64/include/uapi/asm/kvm.h#L203
macro_rules! arm64_sys_reg {
($name: tt, $op0: tt, $op1: tt, $crn: tt, $crm: tt, $op2: tt) => {
const $name: u64 = KVM_REG_ARM64 as u64
| KVM_REG_SIZE_U64 as u64
| KVM_REG_ARM64_SYSREG as u64
| ((($op0 as u64) << KVM_REG_ARM64_SYSREG_OP0_SHIFT)
& KVM_REG_ARM64_SYSREG_OP0_MASK as u64)
| ((($op1 as u64) << KVM_REG_ARM64_SYSREG_OP1_SHIFT)
& KVM_REG_ARM64_SYSREG_OP1_MASK as u64)
| ((($crn as u64) << KVM_REG_ARM64_SYSREG_CRN_SHIFT)
& KVM_REG_ARM64_SYSREG_CRN_MASK as u64)
| ((($crm as u64) << KVM_REG_ARM64_SYSREG_CRM_SHIFT)
& KVM_REG_ARM64_SYSREG_CRM_MASK as u64)
| ((($op2 as u64) << KVM_REG_ARM64_SYSREG_OP2_SHIFT)
& KVM_REG_ARM64_SYSREG_OP2_MASK as u64);
};
}
// Constant imported from the Linux kernel:
// https://elixir.bootlin.com/linux/v4.20.17/source/arch/arm64/include/asm/sysreg.h#L135
arm64_sys_reg!(MPIDR_EL1, 3, 0, 0, 0, 5);
/// Configure core registers for a given CPU.
///
/// # Arguments
@@ -122,77 +43,39 @@ arm64_sys_reg!(MPIDR_EL1, 3, 0, 0, 0, 5);
/// * `cpu_id` - Index of current vcpu.
/// * `boot_ip` - Starting instruction pointer.
/// * `mem` - Reserved DRAM for current VM.
pub fn setup_regs(vcpu: &VcpuFd, cpu_id: u8, boot_ip: u64, mem: &GuestMemoryMmap) -> Result<()> {
pub fn setup_regs(
vcpu: &Arc<dyn hypervisor::Vcpu>,
cpu_id: u8,
boot_ip: u64,
mem: &GuestMemoryMmap,
) -> Result<()> {
let kreg_off = offset__of!(kvm_regs, regs);
// Get the register index of the PSTATE (Processor State) register.
vcpu.set_one_reg(arm64_core_reg!(pstate), PSTATE_FAULT_BITS_64)
.map_err(Error::SetCoreRegister)?;
let pstate = offset__of!(user_pt_regs, pstate) + kreg_off;
vcpu.set_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, pstate),
PSTATE_FAULT_BITS_64,
)
.map_err(Error::SetCoreRegister)?;
// Other vCPUs are powered off initially awaiting PSCI wakeup.
if cpu_id == 0 {
// Setting the PC (Processor Counter) to the current program address (kernel address).
vcpu.set_one_reg(arm64_core_reg!(pc), boot_ip)
let pc = offset__of!(user_pt_regs, pc) + kreg_off;
vcpu.set_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, pc), boot_ip as u64)
.map_err(Error::SetCoreRegister)?;
// Last mandatory thing to set -> the address pointing to the FDT (also called DTB).
// "The device tree blob (dtb) must be placed on an 8-byte boundary and must
// not exceed 2 megabytes in size." -> https://www.kernel.org/doc/Documentation/arm64/booting.txt.
// We are choosing to place it the end of DRAM. See `get_fdt_addr`.
vcpu.set_one_reg(arm64_core_reg!(regs), get_fdt_addr(mem) as u64)
.map_err(Error::SetCoreRegister)?;
let regs0 = offset__of!(user_pt_regs, regs) + kreg_off;
vcpu.set_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0),
get_fdt_addr(mem) as u64,
)
.map_err(Error::SetCoreRegister)?;
}
Ok(())
}
/// Read the MPIDR - Multiprocessor Affinity Register.
///
/// # Arguments
///
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
pub fn read_mpidr(vcpu: &VcpuFd) -> Result<u64> {
vcpu.get_one_reg(MPIDR_EL1).map_err(Error::GetSysRegister)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::aarch64::layout;
use kvm_ioctls::Kvm;
use vm_memory::{GuestAddress, GuestMemoryMmap};
#[test]
fn test_setup_regs() {
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let vcpu = vm.create_vcpu(0).unwrap();
let mut regions = Vec::new();
regions.push((
GuestAddress(layout::RAM_64BIT_START),
(layout::FDT_MAX_SIZE + 0x1000) as usize,
));
let mem = GuestMemoryMmap::from_ranges(&regions).expect("Cannot initialize memory");
match setup_regs(&vcpu, 0, 0x0, &mem).unwrap_err() {
Error::SetCoreRegister(ref e) => assert_eq!(e.errno(), libc::ENOEXEC),
_ => panic!("Expected to receive Error::SetCoreRegister"),
}
let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default();
vm.get_preferred_target(&mut kvi).unwrap();
vcpu.vcpu_init(&kvi).unwrap();
assert!(setup_regs(&vcpu, 0, 0x0, &mem).is_ok());
}
#[test]
fn test_read_mpidr() {
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let vcpu = vm.create_vcpu(0).unwrap();
let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default();
vm.get_preferred_target(&mut kvi).unwrap();
// Must fail when vcpu is not initialized yet.
assert!(read_mpidr(&vcpu).is_err());
vcpu.vcpu_init(&kvi).unwrap();
assert_eq!(read_mpidr(&vcpu).unwrap(), 0x80000000);
}
}

View File

@@ -6,27 +6,27 @@
//! Implements platform specific functionality.
//! Supported platforms: x86_64, aarch64.
#![allow(
clippy::unreadable_literal,
clippy::redundant_static_lifetimes,
clippy::cast_lossless,
clippy::transmute_ptr_to_ptr,
clippy::cast_ptr_alignment
)]
#![allow(clippy::transmute_ptr_to_ptr, clippy::redundant_static_lifetimes)]
extern crate anyhow;
extern crate byteorder;
extern crate kvm_bindings;
extern crate kvm_ioctls;
extern crate hypervisor;
extern crate libc;
extern crate vm_memory;
#[macro_use]
extern crate log;
#[cfg(feature = "acpi")]
extern crate acpi_tables;
extern crate arch_gen;
extern crate linux_loader;
extern crate serde;
extern crate vm_memory;
extern crate vm_migration;
#[cfg(target_arch = "aarch64")]
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate thiserror;
use kvm_ioctls::*;
use std::fmt;
use std::result;
@@ -56,9 +56,7 @@ pub enum Error {
/// Error writing module entry to guest memory.
ModlistSetup(vm_memory::GuestMemoryError),
/// RSDP Beyond Guest Memory
RSDPPastRamEnd,
/// Capability missing
CapabilityMissing(Cap),
RsdpPastRamEnd,
}
/// Type for returning public functions outcome.
@@ -89,8 +87,8 @@ pub mod aarch64;
#[cfg(target_arch = "aarch64")]
pub use aarch64::{
arch_memory_regions, check_required_kvm_extensions, configure_system, configure_vcpu,
fdt::DeviceInfoForFDT, get_host_cpu_phys_bits, get_kernel_start, layout,
arch_memory_regions, configure_system, configure_vcpu, fdt::DeviceInfoForFdt,
get_host_cpu_phys_bits, get_kernel_start, initramfs_load_addr, layout,
layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE, layout::IRQ_MAX, EntryPoint,
};
@@ -99,9 +97,9 @@ pub mod x86_64;
#[cfg(target_arch = "x86_64")]
pub use x86_64::{
arch_memory_regions, check_required_kvm_extensions, configure_system, configure_vcpu,
get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
layout::CMDLINE_START, regs, BootProtocol, CpuidPatch, CpuidReg, EntryPoint,
arch_memory_regions, configure_system, configure_vcpu, get_host_cpu_phys_bits,
initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, regs,
BootProtocol, CpuidPatch, CpuidReg, EntryPoint,
};
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
@@ -130,7 +128,10 @@ pub enum DeviceType {
Serial,
/// Device Type: RTC.
#[cfg(target_arch = "aarch64")]
RTC,
Rtc,
/// Device Type: GPIO.
#[cfg(target_arch = "aarch64")]
Gpio,
}
/// Default (smallest) memory page size for the supported architectures.
@@ -145,13 +146,13 @@ impl fmt::Display for DeviceType {
/// Structure to describe MMIO device information
#[derive(Clone, Debug)]
#[cfg(target_arch = "aarch64")]
pub struct MMIODeviceInfo {
pub struct MmioDeviceInfo {
pub addr: u64,
pub irq: u32,
}
#[cfg(target_arch = "aarch64")]
impl DeviceInfoForFDT for MMIODeviceInfo {
impl DeviceInfoForFdt for MmioDeviceInfo {
fn addr(&self) -> u64 {
self.addr
}
@@ -159,6 +160,6 @@ impl DeviceInfoForFDT for MMIODeviceInfo {
self.irq
}
fn length(&self) -> u64 {
4096 as u64
4096
}
}

View File

@@ -5,30 +5,28 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use hypervisor::x86_64::LapicState;
use std::io::Cursor;
use std::mem;
use std::result;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use kvm_bindings::kvm_lapic_state;
use kvm_ioctls;
use std::sync::Arc;
#[derive(Debug)]
pub enum Error {
GetLapic(kvm_ioctls::Error),
SetLapic(kvm_ioctls::Error),
GetLapic(anyhow::Error),
SetLapic(anyhow::Error),
}
pub type Result<T> = result::Result<T, Error>;
pub type Result<T> = result::Result<T, hypervisor::HypervisorCpuError>;
// Defines poached from apicdef.h kernel header.
const APIC_LVT0: usize = 0x350;
const APIC_LVT1: usize = 0x360;
const APIC_MODE_NMI: u32 = 0x4;
const APIC_MODE_EXTINT: u32 = 0x7;
pub const APIC_LVT0: usize = 0x350;
pub const APIC_LVT1: usize = 0x360;
pub const APIC_MODE_NMI: u32 = 0x4;
pub const APIC_MODE_EXTINT: u32 = 0x7;
fn get_klapic_reg(klapic: &kvm_lapic_state, reg_offset: usize) -> u32 {
pub fn get_klapic_reg(klapic: &LapicState, reg_offset: usize) -> u32 {
let sliceu8 = unsafe {
// This array is only accessed as parts of a u32 word, so interpret it as a u8 array.
// Cursors are only readable on arrays of u8, not i8(c_char).
@@ -41,7 +39,7 @@ fn get_klapic_reg(klapic: &kvm_lapic_state, reg_offset: usize) -> u32 {
.expect("Failed to read klapic register")
}
fn set_klapic_reg(klapic: &mut kvm_lapic_state, reg_offset: usize, value: u32) {
pub fn set_klapic_reg(klapic: &mut LapicState, reg_offset: usize, value: u32) {
let sliceu8 = unsafe {
// This array is only accessed as parts of a u32 word, so interpret it as a u8 array.
// Cursors are only readable on arrays of u8, not i8(c_char).
@@ -54,7 +52,7 @@ fn set_klapic_reg(klapic: &mut kvm_lapic_state, reg_offset: usize, value: u32) {
.expect("Failed to write klapic register")
}
fn set_apic_delivery_mode(reg: u32, mode: u32) -> u32 {
pub fn set_apic_delivery_mode(reg: u32, mode: u32) -> u32 {
((reg) & !0x700) | ((mode) << 8)
}
@@ -62,8 +60,8 @@ fn set_apic_delivery_mode(reg: u32, mode: u32) -> u32 {
///
/// # Arguments
/// * `vcpu` - The VCPU object to configure.
pub fn set_lint(vcpu: &kvm_ioctls::VcpuFd) -> Result<()> {
let mut klapic = vcpu.get_lapic().map_err(Error::GetLapic)?;
pub fn set_lint(vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<()> {
let mut klapic = vcpu.get_lapic()?;
let lvt_lint0 = get_klapic_reg(&klapic, APIC_LVT0);
set_klapic_reg(
@@ -78,24 +76,19 @@ pub fn set_lint(vcpu: &kvm_ioctls::VcpuFd) -> Result<()> {
set_apic_delivery_mode(lvt_lint1, APIC_MODE_NMI),
);
vcpu.set_lapic(&klapic).map_err(Error::SetLapic)
vcpu.set_lapic(&klapic)
}
#[cfg(test)]
mod tests {
extern crate kvm_ioctls;
extern crate rand;
use self::rand::Rng;
use super::*;
use kvm_ioctls::Kvm;
const KVM_APIC_REG_SIZE: usize = 0x400;
#[test]
fn test_set_and_get_klapic_reg() {
let reg_offset = 0x340;
let mut klapic = kvm_lapic_state::default();
let mut klapic = LapicState::default();
set_klapic_reg(&mut klapic, reg_offset, 3);
let value = get_klapic_reg(&klapic, reg_offset);
assert_eq!(value, 3);
@@ -105,54 +98,25 @@ mod tests {
#[should_panic]
fn test_set_and_get_klapic_out_of_bounds() {
let reg_offset = KVM_APIC_REG_SIZE + 10;
let mut klapic = kvm_lapic_state::default();
let mut klapic = LapicState::default();
set_klapic_reg(&mut klapic, reg_offset, 3);
}
#[test]
fn test_apic_delivery_mode() {
let mut rng = rand::thread_rng();
let mut v: Vec<u32> = (0..20).map(|_| rng.gen::<u32>()).collect();
let mut v: Vec<u32> = Vec::new();
v.resize(20, 0);
unsafe {
assert_eq!(
libc::getrandom(v.as_mut_ptr() as *mut _ as *mut libc::c_void, 80, 0),
80
);
}
v.iter_mut()
.for_each(|x| *x = set_apic_delivery_mode(*x, 2));
let after: Vec<u32> = v.iter().map(|x| ((*x & !0x700) | ((2) << 8))).collect();
assert_eq!(v, after);
}
#[test]
fn test_setlint() {
let kvm = kvm_ioctls::Kvm::new().unwrap();
assert!(kvm.check_extension(kvm_ioctls::Cap::Irqchip));
let vm = kvm.create_vm().unwrap();
//the get_lapic ioctl will fail if there is no irqchip created beforehand.
assert!(vm.create_irq_chip().is_ok());
let vcpu = vm.create_vcpu(0).unwrap();
let klapic_before: kvm_lapic_state = vcpu.get_lapic().unwrap();
// Compute the value that is expected to represent LVT0 and LVT1.
let lint0 = get_klapic_reg(&klapic_before, APIC_LVT0);
let lint1 = get_klapic_reg(&klapic_before, APIC_LVT1);
let lint0_mode_expected = set_apic_delivery_mode(lint0, APIC_MODE_EXTINT);
let lint1_mode_expected = set_apic_delivery_mode(lint1, APIC_MODE_NMI);
set_lint(&vcpu).unwrap();
// Compute the value that represents LVT0 and LVT1 after set_lint.
let klapic_actual: kvm_lapic_state = vcpu.get_lapic().unwrap();
let lint0_mode_actual = get_klapic_reg(&klapic_actual, APIC_LVT0);
let lint1_mode_actual = get_klapic_reg(&klapic_actual, APIC_LVT1);
assert_eq!(lint0_mode_expected, lint0_mode_actual);
assert_eq!(lint1_mode_expected, lint1_mode_actual);
}
#[test]
fn test_setlint_fails() {
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let vcpu = vm.create_vcpu(0).unwrap();
// 'get_lapic' ioctl triggered by the 'set_lint' function will fail if there is no
// irqchip created beforehand.
assert!(set_lint(&vcpu).is_err());
}
}

View File

@@ -7,7 +7,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
use vm_memory::{GuestAddress, GuestUsize};
use vm_memory::GuestAddress;
/*
@@ -70,6 +70,8 @@ pub const EBDA_START: GuestAddress = GuestAddress(0xa0000);
// ACPI RSDP table
pub const RSDP_POINTER: GuestAddress = EBDA_START;
pub const SMBIOS_START: u64 = 0xf0000; // First possible location per the spec.
// == End of "EBDA" range ==
// ** High RAM (start: 1MiB, length: 3071MiB) **
@@ -79,22 +81,22 @@ pub const HIGH_RAM_START: GuestAddress = GuestAddress(0x100000);
// ** 32-bit reserved area (start: 3GiB, length: 1GiB) **
pub const MEM_32BIT_RESERVED_START: GuestAddress = GuestAddress(0xc000_0000);
pub const MEM_32BIT_RESERVED_SIZE: GuestUsize = 1024 << 20;
pub const MEM_32BIT_RESERVED_SIZE: u64 = 1024 << 20;
// == Fixed constants within the "32-bit reserved" range ==
// Sub range: 32-bit PCI devices (start: 3GiB, length: 640Mib)
pub const MEM_32BIT_DEVICES_START: GuestAddress = MEM_32BIT_RESERVED_START;
pub const MEM_32BIT_DEVICES_SIZE: GuestUsize = 640 << 20;
pub const MEM_32BIT_DEVICES_SIZE: u64 = 640 << 20;
// PCI MMCONFIG space (start: after the device space, length: 256MiB)
pub const PCI_MMCONFIG_START: GuestAddress =
GuestAddress(MEM_32BIT_DEVICES_START.0 + MEM_32BIT_DEVICES_SIZE);
pub const PCI_MMCONFIG_SIZE: GuestUsize = 256 << 20;
pub const PCI_MMCONFIG_SIZE: u64 = 256 << 20;
// IOAPIC
pub const IOAPIC_START: GuestAddress = GuestAddress(0xfec0_0000);
pub const IOAPIC_SIZE: GuestUsize = 0x20;
pub const IOAPIC_SIZE: u64 = 0x20;
// APIC
pub const APIC_START: GuestAddress = GuestAddress(0xfee0_0000);

View File

@@ -6,17 +6,14 @@
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
mod gdt;
use std::sync::Arc;
pub mod interrupts;
pub mod layout;
#[cfg(not(feature = "acpi"))]
mod mptable;
pub mod regs;
use crate::InitramfsConfig;
use crate::RegionType;
use kvm_bindings::CpuId;
use kvm_ioctls::*;
use hypervisor::{CpuId, CpuIdEntry, CPUID_FLAG_VALID_INDEX};
use linux_loader::loader::bootparam::{boot_params, setup_header};
use linux_loader::loader::elf::start_info::{
hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info,
@@ -26,6 +23,10 @@ use vm_memory::{
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic,
GuestMemoryMmap, GuestMemoryRegion, GuestUsize,
};
mod smbios;
use std::arch::x86_64;
#[cfg(feature = "tdx")]
pub mod tdx;
#[derive(Debug, Copy, Clone)]
pub enum BootProtocol {
@@ -58,6 +59,53 @@ pub struct EntryPoint {
const E820_RAM: u32 = 1;
const E820_RESERVED: u32 = 2;
#[derive(Clone)]
pub struct SgxEpcSection {
start: GuestAddress,
size: GuestUsize,
}
impl SgxEpcSection {
pub fn new(start: GuestAddress, size: GuestUsize) -> Self {
SgxEpcSection { start, size }
}
pub fn start(&self) -> GuestAddress {
self.start
}
pub fn size(&self) -> GuestUsize {
self.size
}
}
#[derive(Clone)]
pub struct SgxEpcRegion {
start: GuestAddress,
size: GuestUsize,
epc_sections: Vec<SgxEpcSection>,
}
impl SgxEpcRegion {
pub fn new(start: GuestAddress, size: GuestUsize) -> Self {
SgxEpcRegion {
start,
size,
epc_sections: Vec::new(),
}
}
pub fn start(&self) -> GuestAddress {
self.start
}
pub fn size(&self) -> GuestUsize {
self.size
}
pub fn epc_sections(&self) -> &Vec<SgxEpcSection> {
&self.epc_sections
}
pub fn push(&mut self, epc_section: SgxEpcSection) {
self.epc_sections.push(epc_section);
}
}
// This is a workaround to the Rust enforcement specifying that any implementation of a foreign
// trait (in this case `DataInit`) where:
// * the type that is implementing the trait is foreign or
@@ -94,27 +142,39 @@ unsafe impl ByteValued for BootParamsWrapper {}
pub enum Error {
/// Invalid e820 setup params.
E820Configuration,
#[cfg(not(feature = "acpi"))]
/// Error writing MP table to memory.
MpTableSetup(mptable::Error),
/// Error configuring the general purpose registers
REGSConfiguration(regs::Error),
RegsConfiguration(regs::Error),
/// Error configuring the special registers
SREGSConfiguration(regs::Error),
SregsConfiguration(regs::Error),
/// Error configuring the floating point related registers
FPUConfiguration(regs::Error),
FpuConfiguration(regs::Error),
/// Error configuring the MSR registers
MSRSConfiguration(regs::Error),
MsrsConfiguration(regs::Error),
/// The call to KVM_SET_CPUID2 failed.
SetSupportedCpusFailed(kvm_ioctls::Error),
/// Failed to set supported CPUs.
SetSupportedCpusFailed(anyhow::Error),
/// Cannot set the local interruption due to bad configuration.
LocalIntConfiguration(interrupts::Error),
LocalIntConfiguration(anyhow::Error),
/// Error setting up SMBIOS table
SmbiosSetup(smbios::Error),
/// Could not find any SGX EPC section
NoSgxEpcSection,
/// Missing SGX CPU feature
MissingSgxFeature,
/// Missing SGX_LC CPU feature
MissingSgxLaunchControlFeature,
}
impl From<Error> for super::Error {
@@ -123,7 +183,7 @@ impl From<Error> for super::Error {
}
}
#[allow(dead_code)]
#[allow(dead_code, clippy::upper_case_acronyms)]
#[derive(Copy, Clone)]
pub enum CpuidReg {
EAX,
@@ -152,8 +212,10 @@ impl CpuidPatch {
) {
let entries = cpuid.as_mut_slice();
let mut entry_found = false;
for entry in entries.iter_mut() {
if entry.function == function && (index == None || index.unwrap() == entry.index) {
entry_found = true;
match reg {
CpuidReg::EAX => {
entry.eax = value;
@@ -170,6 +232,38 @@ impl CpuidPatch {
}
}
}
if entry_found {
return;
}
// Entry not found, so let's add it.
if let Some(index) = index {
let mut entry = CpuIdEntry {
function,
index,
flags: CPUID_FLAG_VALID_INDEX,
..Default::default()
};
match reg {
CpuidReg::EAX => {
entry.eax = value;
}
CpuidReg::EBX => {
entry.ebx = value;
}
CpuidReg::ECX => {
entry.ecx = value;
}
CpuidReg::EDX => {
entry.edx = value;
}
}
if let Err(e) = cpuid.push(entry) {
error!("Failed adding new CPUID entry: {:?}", e);
}
}
}
pub fn patch_cpuid(cpuid: &mut CpuId, patches: Vec<CpuidPatch>) {
@@ -197,21 +291,64 @@ impl CpuidPatch {
}
}
}
pub fn is_feature_enabled(
cpuid: &CpuId,
function: u32,
index: u32,
reg: CpuidReg,
feature_bit: usize,
) -> bool {
let entries = cpuid.as_slice();
let mask = 1 << feature_bit;
for entry in entries.iter() {
if entry.function == function && entry.index == index {
let reg_val: u32;
match reg {
CpuidReg::EAX => {
reg_val = entry.eax;
}
CpuidReg::EBX => {
reg_val = entry.ebx;
}
CpuidReg::ECX => {
reg_val = entry.ecx;
}
CpuidReg::EDX => {
reg_val = entry.edx;
}
}
return (reg_val & mask) == mask;
}
}
false
}
}
pub fn configure_vcpu(
fd: &VcpuFd,
fd: &Arc<dyn hypervisor::Vcpu>,
id: u8,
kernel_entry_point: Option<EntryPoint>,
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
cpuid: CpuId,
kvm_hyperv: bool,
) -> super::Result<()> {
// Per vCPU CPUID changes; common are handled via CpuManager::generate_common_cpuid()
let mut cpuid = cpuid;
CpuidPatch::set_cpuid_reg(&mut cpuid, 0xb, None, CpuidReg::EDX, u32::from(id));
fd.set_cpuid2(&cpuid)
.map_err(Error::SetSupportedCpusFailed)?;
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1f, None, CpuidReg::EDX, u32::from(id));
regs::setup_msrs(fd).map_err(Error::MSRSConfiguration)?;
fd.set_cpuid2(&cpuid)
.map_err(|e| Error::SetSupportedCpusFailed(e.into()))?;
if kvm_hyperv {
fd.enable_hyperv_synic().unwrap();
}
regs::setup_msrs(fd).map_err(Error::MsrsConfiguration)?;
if let Some(kernel_entry_point) = kernel_entry_point {
// Safe to unwrap because this method is called after the VM is configured
regs::setup_regs(
@@ -221,12 +358,12 @@ pub fn configure_vcpu(
layout::ZERO_PAGE_START.raw_value(),
kernel_entry_point.protocol,
)
.map_err(Error::REGSConfiguration)?;
regs::setup_fpu(fd).map_err(Error::FPUConfiguration)?;
.map_err(Error::RegsConfiguration)?;
regs::setup_fpu(fd).map_err(Error::FpuConfiguration)?;
regs::setup_sregs(&vm_memory.memory(), fd, kernel_entry_point.protocol)
.map_err(Error::SREGSConfiguration)?;
.map_err(Error::SregsConfiguration)?;
}
interrupts::set_lint(fd).map_err(Error::LocalIntConfiguration)?;
interrupts::set_lint(fd).map_err(|e| Error::LocalIntConfiguration(e.into()))?;
Ok(())
}
@@ -295,23 +432,34 @@ pub fn configure_system(
setup_hdr: Option<setup_header>,
rsdp_addr: Option<GuestAddress>,
boot_prot: BootProtocol,
sgx_epc_region: Option<SgxEpcRegion>,
) -> super::Result<()> {
// Note that this puts the mptable at the last 1k of Linux's 640k base RAM
#[cfg(not(feature = "acpi"))]
mptable::setup_mptable(guest_mem, _num_cpus).map_err(Error::MpTableSetup)?;
let size = smbios::setup_smbios(guest_mem).map_err(Error::SmbiosSetup)?;
// Place the MP table after the SMIOS table aligned to 16 bytes
let offset = GuestAddress(layout::SMBIOS_START).unchecked_add(size);
let offset = GuestAddress((offset.0 + 16) & !0xf);
mptable::setup_mptable(offset, guest_mem, _num_cpus).map_err(Error::MpTableSetup)?;
// Check that the RAM is not smaller than the RSDP start address
if let Some(rsdp_addr) = rsdp_addr {
if rsdp_addr.0 > guest_mem.last_addr().0 {
return Err(super::Error::RSDPPastRamEnd);
return Err(super::Error::RsdpPastRamEnd);
}
}
match boot_prot {
BootProtocol::PvhBoot => {
configure_pvh(guest_mem, cmdline_addr, initramfs, rsdp_addr)?;
configure_pvh(
guest_mem,
cmdline_addr,
initramfs,
rsdp_addr,
sgx_epc_region,
)?;
}
BootProtocol::LinuxBoot => {
error!("Using deprecated LinuxBoot protocol: Please configure your kernel with CONFIG_PVH=y and supply the `vmlinux` file to `--kernel`");
configure_64bit_boot(
guest_mem,
cmdline_addr,
@@ -319,6 +467,7 @@ pub fn configure_system(
initramfs,
setup_hdr,
rsdp_addr,
sgx_epc_region,
)?;
}
}
@@ -331,6 +480,7 @@ fn configure_pvh(
cmdline_addr: GuestAddress,
initramfs: &Option<InitramfsConfig>,
rsdp_addr: Option<GuestAddress>,
sgx_epc_region: Option<SgxEpcRegion>,
) -> super::Result<()> {
const XEN_HVM_START_MAGIC_VALUE: u32 = 0x336ec578;
@@ -369,7 +519,7 @@ fn configure_pvh(
let mut memmap: Vec<hvm_memmap_table_entry> = Vec::new();
// Create the memory map entries.
add_memmap_entry(&mut memmap, 0, layout::EBDA_START.raw_value(), E820_RAM)?;
add_memmap_entry(&mut memmap, 0, layout::EBDA_START.raw_value(), E820_RAM);
let mem_end = guest_mem.last_addr();
@@ -379,21 +529,21 @@ fn configure_pvh(
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,
)?;
);
}
}
@@ -402,7 +552,16 @@ fn configure_pvh(
layout::PCI_MMCONFIG_START.0,
layout::PCI_MMCONFIG_SIZE,
E820_RESERVED,
)?;
);
if let Some(sgx_epc_region) = sgx_epc_region {
add_memmap_entry(
&mut memmap,
sgx_epc_region.start().raw_value(),
sgx_epc_region.size() as u64,
E820_RESERVED,
);
}
start_info.0.memmap_entries = memmap.len() as u32;
@@ -446,12 +605,7 @@ fn configure_pvh(
Ok(())
}
fn add_memmap_entry(
memmap: &mut Vec<hvm_memmap_table_entry>,
addr: u64,
size: u64,
mem_type: u32,
) -> Result<(), Error> {
fn add_memmap_entry(memmap: &mut Vec<hvm_memmap_table_entry>, addr: u64, size: u64, mem_type: u32) {
// Add the table entry to the vector
memmap.push(hvm_memmap_table_entry {
addr,
@@ -459,8 +613,6 @@ fn add_memmap_entry(
type_: mem_type,
reserved: 0,
});
Ok(())
}
fn configure_64bit_boot(
@@ -470,6 +622,7 @@ fn configure_64bit_boot(
initramfs: &Option<InitramfsConfig>,
setup_hdr: Option<setup_header>,
rsdp_addr: Option<GuestAddress>,
sgx_epc_region: Option<SgxEpcRegion>,
) -> super::Result<()> {
const KERNEL_BOOT_FLAG_MAGIC: u16 = 0xaa55;
const KERNEL_HDR_MAGIC: u32 = 0x53726448;
@@ -533,6 +686,15 @@ fn configure_64bit_boot(
E820_RESERVED,
)?;
if let Some(sgx_epc_region) = sgx_epc_region {
add_e820_entry(
&mut params.0,
sgx_epc_region.start().raw_value(),
sgx_epc_region.size() as u64,
E820_RESERVED,
)?;
}
if let Some(rsdp_addr) = rsdp_addr {
params.0.acpi_rsdp_addr = rsdp_addr.0;
}
@@ -588,7 +750,6 @@ pub fn initramfs_load_addr(
}
pub fn get_host_cpu_phys_bits() -> u8 {
use std::arch::x86_64;
unsafe {
let leaf = x86_64::__cpuid(0x8000_0000);
@@ -615,16 +776,112 @@ pub fn get_host_cpu_phys_bits() -> u8 {
}
}
pub fn check_required_kvm_extensions(kvm: &Kvm) -> super::Result<()> {
if !kvm.check_extension(Cap::SignalMsi) {
return Err(super::Error::CapabilityMissing(Cap::SignalMsi));
pub fn update_cpuid_topology(
cpuid: &mut CpuId,
threads_per_core: u8,
cores_per_die: u8,
dies_per_package: u8,
) {
let thread_width = 8 - (threads_per_core - 1).leading_zeros();
let core_width = (8 - (cores_per_die - 1).leading_zeros()) + thread_width;
let die_width = (8 - (dies_per_package - 1).leading_zeros()) + core_width;
// CPU Topology leaf 0xb
CpuidPatch::set_cpuid_reg(cpuid, 0xb, Some(0), CpuidReg::EAX, thread_width);
CpuidPatch::set_cpuid_reg(
cpuid,
0xb,
Some(0),
CpuidReg::EBX,
u32::from(threads_per_core),
);
CpuidPatch::set_cpuid_reg(cpuid, 0xb, Some(0), CpuidReg::ECX, 1 << 8);
CpuidPatch::set_cpuid_reg(cpuid, 0xb, Some(1), CpuidReg::EAX, die_width);
CpuidPatch::set_cpuid_reg(
cpuid,
0xb,
Some(1),
CpuidReg::EBX,
u32::from(dies_per_package * cores_per_die * threads_per_core),
);
CpuidPatch::set_cpuid_reg(cpuid, 0xb, Some(1), CpuidReg::ECX, 2 << 8);
// CPU Topology leaf 0x1f
CpuidPatch::set_cpuid_reg(cpuid, 0x1f, Some(0), CpuidReg::EAX, thread_width);
CpuidPatch::set_cpuid_reg(
cpuid,
0x1f,
Some(0),
CpuidReg::EBX,
u32::from(threads_per_core),
);
CpuidPatch::set_cpuid_reg(cpuid, 0x1f, Some(0), CpuidReg::ECX, 1 << 8);
CpuidPatch::set_cpuid_reg(cpuid, 0x1f, Some(1), CpuidReg::EAX, core_width);
CpuidPatch::set_cpuid_reg(
cpuid,
0x1f,
Some(1),
CpuidReg::EBX,
u32::from(cores_per_die * threads_per_core),
);
CpuidPatch::set_cpuid_reg(cpuid, 0x1f, Some(1), CpuidReg::ECX, 2 << 8);
CpuidPatch::set_cpuid_reg(cpuid, 0x1f, Some(2), CpuidReg::EAX, die_width);
CpuidPatch::set_cpuid_reg(
cpuid,
0x1f,
Some(2),
CpuidReg::EBX,
u32::from(dies_per_package * cores_per_die * threads_per_core),
);
CpuidPatch::set_cpuid_reg(cpuid, 0x1f, Some(2), CpuidReg::ECX, 5 << 8);
}
// The goal is to update the CPUID sub-leaves to reflect the number of EPC
// sections exposed to the guest.
pub fn update_cpuid_sgx(cpuid: &mut CpuId, epc_sections: Vec<SgxEpcSection>) -> Result<(), Error> {
// Something's wrong if there's no EPC section.
if epc_sections.is_empty() {
return Err(Error::NoSgxEpcSection);
}
if !kvm.check_extension(Cap::TscDeadlineTimer) {
return Err(super::Error::CapabilityMissing(Cap::TscDeadlineTimer));
// We can't go further if the hypervisor does not support SGX feature.
if !CpuidPatch::is_feature_enabled(cpuid, 0x7, 0, CpuidReg::EBX, 2) {
return Err(Error::MissingSgxFeature);
}
if !kvm.check_extension(Cap::SplitIrqchip) {
return Err(super::Error::CapabilityMissing(Cap::SplitIrqchip));
// We can't go further if the hypervisor does not support SGX_LC feature.
if !CpuidPatch::is_feature_enabled(cpuid, 0x7, 0, CpuidReg::ECX, 30) {
return Err(Error::MissingSgxLaunchControlFeature);
}
// Get host CPUID for leaf 0x12, subleaf 0x2. This is to retrieve EPC
// properties such as confidentiality and integrity.
let leaf = unsafe { std::arch::x86_64::__cpuid_count(0x12, 0x2) };
for (i, epc_section) in epc_sections.iter().enumerate() {
let subleaf_idx = i + 2;
let start = epc_section.start().raw_value();
let size = epc_section.size() as u64;
let eax = (start & 0xffff_f000) as u32 | 0x1;
let ebx = (start >> 32) as u32;
let ecx = (size & 0xffff_f000) as u32 | (leaf.ecx & 0xf);
let edx = (size >> 32) as u32;
// CPU Topology leaf 0x12
CpuidPatch::set_cpuid_reg(cpuid, 0x12, Some(subleaf_idx as u32), CpuidReg::EAX, eax);
CpuidPatch::set_cpuid_reg(cpuid, 0x12, Some(subleaf_idx as u32), CpuidReg::EBX, ebx);
CpuidPatch::set_cpuid_reg(cpuid, 0x12, Some(subleaf_idx as u32), CpuidReg::ECX, ecx);
CpuidPatch::set_cpuid_reg(cpuid, 0x12, Some(subleaf_idx as u32), CpuidReg::EDX, edx);
}
// Add one NULL entry to terminate the dynamic list
let subleaf_idx = epc_sections.len() + 2;
// CPU Topology leaf 0x12
CpuidPatch::set_cpuid_reg(cpuid, 0x12, Some(subleaf_idx as u32), CpuidReg::EAX, 0);
CpuidPatch::set_cpuid_reg(cpuid, 0x12, Some(subleaf_idx as u32), CpuidReg::EBX, 0);
CpuidPatch::set_cpuid_reg(cpuid, 0x12, Some(subleaf_idx as u32), CpuidReg::ECX, 0);
CpuidPatch::set_cpuid_reg(cpuid, 0x12, Some(subleaf_idx as u32), CpuidReg::EDX, 0);
Ok(())
}
@@ -635,7 +892,7 @@ mod tests {
#[test]
fn regions_lt_4gb() {
let regions = arch_memory_regions(1 << 29 as GuestUsize);
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);
@@ -643,7 +900,7 @@ mod tests {
#[test]
fn regions_gt_4gb() {
let regions = arch_memory_regions((1 << 32 as GuestUsize) + 0x8000);
let regions = arch_memory_regions((1 << 32) + 0x8000);
assert_eq!(4, regions.len());
assert_eq!(GuestAddress(0), regions[0].0);
assert_eq!(GuestAddress(1 << 32), regions[1].0);
@@ -652,7 +909,7 @@ mod tests {
#[test]
fn test_system_configuration() {
let no_vcpus = 4;
let gm = GuestMemoryMmap::from_ranges(&vec![(GuestAddress(0), 0x10000)]).unwrap();
let gm = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
let config_err = configure_system(
&gm,
GuestAddress(0),
@@ -662,6 +919,7 @@ mod tests {
None,
Some(layout::RSDP_POINTER),
BootProtocol::LinuxBoot,
None,
);
assert!(config_err.is_err());
@@ -683,6 +941,7 @@ mod tests {
None,
None,
BootProtocol::LinuxBoot,
None,
)
.unwrap();
@@ -695,6 +954,7 @@ mod tests {
None,
None,
BootProtocol::PvhBoot,
None,
)
.unwrap();
@@ -716,6 +976,7 @@ mod tests {
None,
None,
BootProtocol::LinuxBoot,
None,
)
.unwrap();
@@ -728,6 +989,7 @@ mod tests {
None,
None,
BootProtocol::PvhBoot,
None,
)
.unwrap();
@@ -749,6 +1011,7 @@ mod tests {
None,
None,
BootProtocol::LinuxBoot,
None,
)
.unwrap();
@@ -761,6 +1024,7 @@ mod tests {
None,
None,
BootProtocol::PvhBoot,
None,
)
.unwrap();
}
@@ -824,8 +1088,8 @@ mod tests {
},
];
add_memmap_entry(&mut memmap, 0, 0x1000, E820_RAM).unwrap();
add_memmap_entry(&mut memmap, 0x10000, 0xa000, E820_RESERVED).unwrap();
add_memmap_entry(&mut memmap, 0, 0x1000, E820_RAM);
add_memmap_entry(&mut memmap, 0x10000, 0xa000, E820_RESERVED);
assert_eq!(format!("{:?}", memmap), format!("{:?}", expected_memmap));
}

View File

@@ -13,8 +13,10 @@ use std::slice;
use libc::c_char;
use arch_gen::x86::mpspec;
use layout::{APIC_START, IOAPIC_START, MPTABLE_START};
use vm_memory::{Address, ByteValued, Bytes, GuestMemory, GuestMemoryError, GuestMemoryMmap};
use layout::{APIC_START, HIGH_RAM_START, IOAPIC_START};
use vm_memory::{
Address, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryError, GuestMemoryMmap,
};
// This is a workaround to the Rust enforcement specifying that any implementation of a foreign
// trait (in this case `ByteValued`) where:
@@ -121,16 +123,21 @@ fn compute_mp_size(num_cpus: u8) -> usize {
}
/// Performs setup of the MP table for the given `num_cpus`.
pub fn setup_mptable(mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> {
pub fn setup_mptable(offset: GuestAddress, mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> {
if num_cpus as u32 > MAX_SUPPORTED_CPUS {
return Err(Error::TooManyCpus);
}
// Used to keep track of the next base pointer into the MP table.
let mut base_mp = MPTABLE_START;
let mut base_mp = offset;
let mp_size = compute_mp_size(num_cpus);
if offset.unchecked_add(mp_size as u64) >= HIGH_RAM_START {
warn!("Skipping mptable creation due to insufficient space");
return Ok(());
}
let mut checksum: u8 = 0;
let ioapicid: u8 = num_cpus + 1;
@@ -280,6 +287,7 @@ pub fn setup_mptable(mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> {
#[cfg(test)]
mod tests {
use super::*;
use layout::MPTABLE_START;
use vm_memory::{GuestAddress, GuestUsize};
fn table_entry_size(type_: u8) -> usize {
@@ -299,7 +307,7 @@ mod tests {
let mem =
GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus))]).unwrap();
setup_mptable(&mem, num_cpus).unwrap();
setup_mptable(MPTABLE_START, &mem, num_cpus).unwrap();
}
#[test]
@@ -308,7 +316,7 @@ mod tests {
let mem = GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus) - 1)])
.unwrap();
assert!(setup_mptable(&mem, num_cpus).is_err());
assert!(setup_mptable(MPTABLE_START, &mem, num_cpus).is_err());
}
#[test]
@@ -317,7 +325,7 @@ mod tests {
let mem =
GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus))]).unwrap();
setup_mptable(&mem, num_cpus).unwrap();
setup_mptable(MPTABLE_START, &mem, num_cpus).unwrap();
let mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap();
@@ -333,7 +341,7 @@ mod tests {
let mem =
GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus))]).unwrap();
setup_mptable(&mem, num_cpus).unwrap();
setup_mptable(MPTABLE_START, &mem, num_cpus).unwrap();
let mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap();
let mpc_offset = GuestAddress(mpf_intel.0.physptr as GuestUsize);
@@ -367,7 +375,7 @@ mod tests {
.unwrap();
for i in 0..MAX_SUPPORTED_CPUS as u8 {
setup_mptable(&mem, i).unwrap();
setup_mptable(MPTABLE_START, &mem, i).unwrap();
let mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap();
let mpc_offset = GuestAddress(mpf_intel.0.physptr as GuestUsize);
@@ -400,7 +408,7 @@ mod tests {
let mem =
GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(cpus as u8))]).unwrap();
let result = setup_mptable(&mem, cpus as u8);
let result = setup_mptable(MPTABLE_START, &mem, cpus as u8);
assert!(result.is_err());
}
}

View File

@@ -6,49 +6,44 @@
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
use std::sync::Arc;
use std::{mem, result};
use super::gdt::{gdt_entry, kvm_segment_from_gdt};
use super::BootProtocol;
use arch_gen::x86::msr_index;
use kvm_bindings::{kvm_fpu, kvm_msr_entry, kvm_regs, kvm_sregs, Msrs};
use kvm_ioctls::VcpuFd;
use hypervisor::arch::x86::gdt::{gdt_entry, segment_from_gdt};
use hypervisor::arch::x86::regs::*;
use hypervisor::x86_64::{FpuState, SpecialRegisters, StandardRegisters};
use layout::{
BOOT_GDT_START, BOOT_IDT_START, PDE_START, PDPTE_START, PML4_START, PML5_START, PVH_INFO_START,
};
use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError, GuestMemoryMmap};
// MTRR constants
const MTRR_ENABLE: u64 = 0x800; // IA32_MTRR_DEF_TYPE MSR: E (MTRRs enabled) flag, bit 11
const MTRR_MEM_TYPE_WB: u64 = 0x6;
#[derive(Debug)]
pub enum Error {
/// Failed to get SREGs for this CPU.
GetStatusRegisters(kvm_ioctls::Error),
GetStatusRegisters(hypervisor::HypervisorCpuError),
/// Failed to set base registers for this CPU.
SetBaseRegisters(kvm_ioctls::Error),
SetBaseRegisters(hypervisor::HypervisorCpuError),
/// Failed to configure the FPU.
SetFPURegisters(kvm_ioctls::Error),
SetFpuRegisters(hypervisor::HypervisorCpuError),
/// Setting up MSRs failed.
SetModelSpecificRegisters(kvm_ioctls::Error),
SetModelSpecificRegisters(hypervisor::HypervisorCpuError),
/// Failed to set SREGs for this CPU.
SetStatusRegisters(kvm_ioctls::Error),
SetStatusRegisters(hypervisor::HypervisorCpuError),
/// Checking the GDT address failed.
CheckGDTAddr,
CheckGdtAddr,
/// Writing the GDT to RAM failed.
WriteGDT(GuestMemoryError),
WriteGdt(GuestMemoryError),
/// Writing the IDT to RAM failed.
WriteIDT(GuestMemoryError),
WriteIdt(GuestMemoryError),
/// Writing PDPTE to RAM failed.
WritePDPTEAddress(GuestMemoryError),
WritePdpteAddress(GuestMemoryError),
/// Writing PDE to RAM failed.
WritePDEAddress(GuestMemoryError),
WritePdeAddress(GuestMemoryError),
/// Writing PML4 to RAM failed.
WritePML4Address(GuestMemoryError),
WritePml4Address(GuestMemoryError),
/// Writing PML5 to RAM failed.
WritePML5Address(GuestMemoryError),
WritePml5Address(GuestMemoryError),
}
pub type Result<T> = result::Result<T, Error>;
@@ -58,14 +53,14 @@ pub type Result<T> = result::Result<T, Error>;
/// # Arguments
///
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
pub fn setup_fpu(vcpu: &VcpuFd) -> Result<()> {
let fpu: kvm_fpu = kvm_fpu {
pub fn setup_fpu(vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<()> {
let fpu: FpuState = FpuState {
fcw: 0x37f,
mxcsr: 0x1f80,
..Default::default()
};
vcpu.set_fpu(&fpu).map_err(Error::SetFPURegisters)
vcpu.set_fpu(&fpu).map_err(Error::SetFpuRegisters)
}
/// Configure Model Specific Registers (MSRs) for a given CPU.
@@ -73,8 +68,8 @@ pub fn setup_fpu(vcpu: &VcpuFd) -> Result<()> {
/// # Arguments
///
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
pub fn setup_msrs(vcpu: &VcpuFd) -> Result<()> {
vcpu.set_msrs(&boot_msr_entries())
pub fn setup_msrs(vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<()> {
vcpu.set_msrs(&hypervisor::x86_64::boot_msr_entries())
.map_err(Error::SetModelSpecificRegisters)?;
Ok(())
@@ -89,22 +84,22 @@ pub fn setup_msrs(vcpu: &VcpuFd) -> Result<()> {
/// * `boot_sp` - Starting stack pointer.
/// * `boot_si` - Must point to zero page address per Linux ABI.
pub fn setup_regs(
vcpu: &VcpuFd,
vcpu: &Arc<dyn hypervisor::Vcpu>,
boot_ip: u64,
boot_sp: u64,
boot_si: u64,
boot_prot: BootProtocol,
) -> Result<()> {
let regs: kvm_regs = match boot_prot {
let regs: StandardRegisters = match boot_prot {
// Configure regs as required by PVH boot protocol.
BootProtocol::PvhBoot => kvm_regs {
BootProtocol::PvhBoot => StandardRegisters {
rflags: 0x0000000000000002u64,
rbx: PVH_INFO_START.raw_value(),
rip: boot_ip,
..Default::default()
},
// Configure regs as required by Linux 64-bit boot protocol.
BootProtocol::LinuxBoot => kvm_regs {
BootProtocol::LinuxBoot => StandardRegisters {
rflags: 0x0000000000000002u64,
rip: boot_ip,
rsp: boot_sp,
@@ -122,8 +117,12 @@ pub fn setup_regs(
///
/// * `mem` - The memory that will be passed to the guest.
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
pub fn setup_sregs(mem: &GuestMemoryMmap, vcpu: &VcpuFd, boot_prot: BootProtocol) -> Result<()> {
let mut sregs: kvm_sregs = vcpu.get_sregs().map_err(Error::GetStatusRegisters)?;
pub fn setup_sregs(
mem: &GuestMemoryMmap,
vcpu: &Arc<dyn hypervisor::Vcpu>,
boot_prot: BootProtocol,
) -> Result<()> {
let mut sregs: SpecialRegisters = vcpu.get_sregs().map_err(Error::GetStatusRegisters)?;
configure_segments_and_sregs(mem, &mut sregs, boot_prot)?;
@@ -136,21 +135,13 @@ pub fn setup_sregs(mem: &GuestMemoryMmap, vcpu: &VcpuFd, boot_prot: BootProtocol
const BOOT_GDT_MAX: usize = 4;
const EFER_LMA: u64 = 0x400;
const EFER_LME: u64 = 0x100;
const X86_CR0_PE: u64 = 0x1;
const X86_CR0_PG: u64 = 0x80000000;
const X86_CR4_PAE: u64 = 0x20;
const X86_CR4_LA57: u64 = 0x1000;
fn write_gdt_table(table: &[u64], guest_mem: &GuestMemoryMmap) -> Result<()> {
let boot_gdt_addr = BOOT_GDT_START;
for (index, entry) in table.iter().enumerate() {
let addr = guest_mem
.checked_offset(boot_gdt_addr, index * mem::size_of::<u64>())
.ok_or(Error::CheckGDTAddr)?;
guest_mem.write_obj(*entry, addr).map_err(Error::WriteGDT)?;
.ok_or(Error::CheckGdtAddr)?;
guest_mem.write_obj(*entry, addr).map_err(Error::WriteGdt)?;
}
Ok(())
}
@@ -159,12 +150,12 @@ fn write_idt_value(val: u64, guest_mem: &GuestMemoryMmap) -> Result<()> {
let boot_idt_addr = BOOT_IDT_START;
guest_mem
.write_obj(val, boot_idt_addr)
.map_err(Error::WriteIDT)
.map_err(Error::WriteIdt)
}
fn configure_segments_and_sregs(
pub fn configure_segments_and_sregs(
mem: &GuestMemoryMmap,
sregs: &mut kvm_sregs,
sregs: &mut SpecialRegisters,
boot_prot: BootProtocol,
) -> Result<()> {
let gdt_table: [u64; BOOT_GDT_MAX as usize] = match boot_prot {
@@ -188,9 +179,9 @@ fn configure_segments_and_sregs(
}
};
let code_seg = kvm_segment_from_gdt(gdt_table[1], 1);
let data_seg = kvm_segment_from_gdt(gdt_table[2], 2);
let tss_seg = kvm_segment_from_gdt(gdt_table[3], 3);
let code_seg = segment_from_gdt(gdt_table[1], 1);
let data_seg = segment_from_gdt(gdt_table[2], 2);
let tss_seg = segment_from_gdt(gdt_table[3], 3);
// Write segments
write_gdt_table(&gdt_table[..], mem)?;
@@ -211,12 +202,12 @@ fn configure_segments_and_sregs(
match boot_prot {
BootProtocol::PvhBoot => {
sregs.cr0 = X86_CR0_PE;
sregs.cr0 = CR0_PE;
sregs.cr4 = 0;
}
BootProtocol::LinuxBoot => {
/* 64-bit protected mode */
sregs.cr0 |= X86_CR0_PE;
sregs.cr0 |= CR0_PE;
sregs.efer |= EFER_LME | EFER_LMA;
}
}
@@ -224,91 +215,49 @@ fn configure_segments_and_sregs(
Ok(())
}
fn setup_page_tables(mem: &GuestMemoryMmap, sregs: &mut kvm_sregs) -> Result<()> {
pub fn setup_page_tables(mem: &GuestMemoryMmap, sregs: &mut SpecialRegisters) -> Result<()> {
// Puts PML5 or PML4 right after zero page but aligned to 4k.
if unsafe { std::arch::x86_64::__cpuid(7).ecx } & (1 << 16) != 0 {
// Entry covering VA [0..256TB)
mem.write_obj(PML4_START.raw_value() | 0x03, PML5_START)
.map_err(Error::WritePML5Address)?;
.map_err(Error::WritePml5Address)?;
sregs.cr3 = PML5_START.raw_value();
sregs.cr4 |= X86_CR4_LA57;
sregs.cr4 |= CR4_LA57;
} else {
sregs.cr3 = PML4_START.raw_value();
}
// Entry covering VA [0..512GB)
mem.write_obj(PDPTE_START.raw_value() | 0x03, PML4_START)
.map_err(Error::WritePML4Address)?;
.map_err(Error::WritePml4Address)?;
// Entry covering VA [0..1GB)
mem.write_obj(PDE_START.raw_value() | 0x03, PDPTE_START)
.map_err(Error::WritePDPTEAddress)?;
.map_err(Error::WritePdpteAddress)?;
// 512 2MB entries together covering VA [0..1GB). Note we are assuming
// CPU supports 2MB pages (/proc/cpuinfo has 'pse'). All modern CPUs do.
for i in 0..512 {
mem.write_obj((i << 21) + 0x83u64, PDE_START.unchecked_add(i * 8))
.map_err(Error::WritePDEAddress)?;
.map_err(Error::WritePdeAddress)?;
}
sregs.cr4 |= X86_CR4_PAE;
sregs.cr0 |= X86_CR0_PG;
sregs.cr4 |= CR4_PAE;
sregs.cr0 |= CR0_PG;
Ok(())
}
macro_rules! kvm_msr {
($msr:expr) => {
kvm_msr_entry {
index: $msr,
data: 0x0,
..Default::default()
}
};
}
macro_rules! kvm_msr_data {
($msr:expr, $data:expr) => {
kvm_msr_entry {
index: $msr,
data: $data,
..Default::default()
}
};
}
pub fn boot_msr_entries() -> Msrs {
Msrs::from_entries(&[
kvm_msr!(msr_index::MSR_IA32_SYSENTER_CS),
kvm_msr!(msr_index::MSR_IA32_SYSENTER_ESP),
kvm_msr!(msr_index::MSR_IA32_SYSENTER_EIP),
kvm_msr!(msr_index::MSR_STAR),
kvm_msr!(msr_index::MSR_CSTAR),
kvm_msr!(msr_index::MSR_LSTAR),
kvm_msr!(msr_index::MSR_KERNEL_GS_BASE),
kvm_msr!(msr_index::MSR_SYSCALL_MASK),
kvm_msr!(msr_index::MSR_IA32_TSC),
kvm_msr_data!(
msr_index::MSR_IA32_MISC_ENABLE,
msr_index::MSR_IA32_MISC_ENABLE_FAST_STRING as u64
),
kvm_msr_data!(msr_index::MSR_MTRRdefType, MTRR_ENABLE | MTRR_MEM_TYPE_WB),
])
}
#[cfg(test)]
mod tests {
extern crate kvm_ioctls;
extern crate vm_memory;
use super::*;
use kvm_ioctls::Kvm;
use vm_memory::{GuestAddress, GuestMemoryMmap};
fn create_guest_mem() -> GuestMemoryMmap {
GuestMemoryMmap::from_ranges(&vec![(GuestAddress(0), 0x10000)]).unwrap()
GuestMemoryMmap::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap()
}
fn read_u64(gm: &GuestMemoryMmap, offset: GuestAddress) -> u64 {
@@ -317,7 +266,7 @@ mod tests {
#[test]
fn segments_and_sregs() {
let mut sregs: kvm_sregs = Default::default();
let mut sregs: SpecialRegisters = Default::default();
let gm = create_guest_mem();
configure_segments_and_sregs(&gm, &mut sregs, BootProtocol::LinuxBoot).unwrap();
@@ -345,7 +294,7 @@ mod tests {
assert_eq!(0, sregs.tr.base);
assert_eq!(0xffffffff, sregs.tr.limit);
assert_eq!(0, sregs.tr.avl);
assert_eq!(X86_CR0_PE, sregs.cr0);
assert_eq!(CR0_PE, sregs.cr0);
assert_eq!(EFER_LME | EFER_LMA, sregs.efer);
configure_segments_and_sregs(&gm, &mut sregs, BootProtocol::PvhBoot).unwrap();
@@ -375,13 +324,13 @@ mod tests {
assert_eq!(0x67, sregs.tr.limit);
assert_eq!(0xb, sregs.tr.type_);
assert_eq!(0, sregs.tr.avl);
assert_eq!(X86_CR0_PE, sregs.cr0);
assert_eq!(CR0_PE, sregs.cr0);
assert_eq!(0, sregs.cr4);
}
#[test]
fn page_tables() {
let mut sregs: kvm_sregs = Default::default();
let mut sregs: SpecialRegisters = Default::default();
let gm = create_guest_mem();
setup_page_tables(&gm, &mut sregs).unwrap();
@@ -402,99 +351,7 @@ mod tests {
} else {
assert_eq!(PML4_START.raw_value(), sregs.cr3);
}
assert_eq!(X86_CR4_PAE, sregs.cr4);
assert_eq!(X86_CR0_PG, sregs.cr0);
}
#[test]
fn test_setup_fpu() {
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let vcpu = vm.create_vcpu(0).unwrap();
setup_fpu(&vcpu).unwrap();
let expected_fpu: kvm_fpu = kvm_fpu {
fcw: 0x37f,
mxcsr: 0x1f80,
..Default::default()
};
let actual_fpu: kvm_fpu = vcpu.get_fpu().unwrap();
// TODO: auto-generate kvm related structures with PartialEq on.
assert_eq!(expected_fpu.fcw, actual_fpu.fcw);
// Setting the mxcsr register from kvm_fpu inside setup_fpu does not influence anything.
// See 'kvm_arch_vcpu_ioctl_set_fpu' from arch/x86/kvm/x86.c.
// The mxcsr will stay 0 and the assert below fails. Decide whether or not we should
// remove it at all.
// assert!(expected_fpu.mxcsr == actual_fpu.mxcsr);
}
#[test]
fn test_setup_msrs() {
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let vcpu = vm.create_vcpu(0).unwrap();
setup_msrs(&vcpu).unwrap();
// This test will check against the last MSR entry configured (the tenth one).
// See create_msr_entries for details.
let mut msrs = Msrs::from_entries(&[kvm_msr_entry {
index: msr_index::MSR_IA32_MISC_ENABLE,
..Default::default()
}]);
// get_msrs returns the number of msrs that it succeed in reading. We only want to read 1
// in this test case scenario.
let read_msrs = vcpu.get_msrs(&mut msrs).unwrap();
assert_eq!(read_msrs, 1);
// Official entries that were setup when we did setup_msrs. We need to assert that the
// tenth one (i.e the one with index msr_index::MSR_IA32_MISC_ENABLE has the data we
// expect.
let entry_vec = boot_msr_entries();
assert_eq!(entry_vec.as_slice()[9], msrs.as_slice()[0]);
}
#[test]
fn test_setup_regs() {
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let vcpu = vm.create_vcpu(0).unwrap();
let expected_regs: kvm_regs = kvm_regs {
rflags: 0x0000000000000002u64,
rip: 1,
rsp: 2,
rbp: 2,
rsi: 3,
..Default::default()
};
setup_regs(
&vcpu,
expected_regs.rip,
expected_regs.rsp,
expected_regs.rsi,
BootProtocol::LinuxBoot,
)
.unwrap();
let actual_regs: kvm_regs = vcpu.get_regs().unwrap();
assert_eq!(actual_regs, expected_regs);
}
#[test]
fn test_setup_sregs() {
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let vcpu = vm.create_vcpu(0).unwrap();
let mut expected_sregs: kvm_sregs = vcpu.get_sregs().unwrap();
let gm = create_guest_mem();
configure_segments_and_sregs(&gm, &mut expected_sregs, BootProtocol::LinuxBoot).unwrap();
setup_page_tables(&gm, &mut expected_sregs).unwrap();
setup_sregs(&gm, &vcpu, BootProtocol::LinuxBoot).unwrap();
let actual_sregs: kvm_sregs = vcpu.get_sregs().unwrap();
assert_eq!(expected_sregs, actual_sregs);
assert_eq!(CR4_PAE, sregs.cr4);
assert_eq!(CR0_PG, sregs.cr0);
}
}

271
arch/src/x86_64/smbios.rs Normal file
View File

@@ -0,0 +1,271 @@
// Copyright © 2020 Intel Corporation
//
// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use layout::SMBIOS_START;
use std::fmt::{self, Display};
use std::mem;
use std::result;
use std::slice;
use vm_memory::ByteValued;
use vm_memory::{Address, Bytes, GuestAddress, GuestMemoryMmap};
#[allow(unused_variables)]
#[derive(Debug)]
pub enum Error {
/// There was too little guest memory to store the entire SMBIOS table.
NotEnoughMemory,
/// The SMBIOS table has too little address space to be stored.
AddressOverflow,
/// Failure while zeroing out the memory for the SMBIOS table.
Clear,
/// Failure to write SMBIOS entrypoint structure
WriteSmbiosEp,
/// Failure to write additional data to memory
WriteData,
}
impl std::error::Error for Error {}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Error::*;
let description = match self {
NotEnoughMemory => "There was too little guest memory to store the SMBIOS table",
AddressOverflow => "The SMBIOS table has too little address space to be stored",
Clear => "Failure while zeroing out the memory for the SMBIOS table",
WriteSmbiosEp => "Failure to write SMBIOS entrypoint structure",
WriteData => "Failure to write additional data to memory",
};
write!(f, "SMBIOS error: {}", description)
}
}
pub type Result<T> = result::Result<T, Error>;
// Constants sourced from SMBIOS Spec 3.2.0.
const SM3_MAGIC_IDENT: &[u8; 5usize] = b"_SM3_";
const BIOS_INFORMATION: u8 = 0;
const SYSTEM_INFORMATION: u8 = 1;
const END_OF_TABLE: u8 = 127;
const PCI_SUPPORTED: u64 = 1 << 7;
const IS_VIRTUAL_MACHINE: u8 = 1 << 4;
fn compute_checksum<T: Copy>(v: &T) -> u8 {
// Safe because we are only reading the bytes within the size of the `T` reference `v`.
let v_slice = unsafe { slice::from_raw_parts(v as *const T as *const u8, mem::size_of::<T>()) };
let mut checksum: u8 = 0;
for i in v_slice.iter() {
checksum = checksum.wrapping_add(*i);
}
(!checksum).wrapping_add(1)
}
#[repr(packed)]
#[derive(Default, Copy)]
pub struct Smbios30Entrypoint {
pub signature: [u8; 5usize],
pub checksum: u8,
pub length: u8,
pub majorver: u8,
pub minorver: u8,
pub docrev: u8,
pub revision: u8,
pub reserved: u8,
pub max_size: u32,
pub physptr: u64,
}
unsafe impl ByteValued for Smbios30Entrypoint {}
impl Clone for Smbios30Entrypoint {
fn clone(&self) -> Self {
*self
}
}
#[repr(packed)]
#[derive(Default, Copy)]
pub struct SmbiosBiosInfo {
pub typ: u8,
pub length: u8,
pub handle: u16,
pub vendor: u8,
pub version: u8,
pub start_addr: u16,
pub release_date: u8,
pub rom_size: u8,
pub characteristics: u64,
pub characteristics_ext1: u8,
pub characteristics_ext2: u8,
}
impl Clone for SmbiosBiosInfo {
fn clone(&self) -> Self {
*self
}
}
unsafe impl ByteValued for SmbiosBiosInfo {}
#[repr(packed)]
#[derive(Default, Copy)]
pub struct SmbiosSysInfo {
pub typ: u8,
pub length: u8,
pub handle: u16,
pub manufacturer: u8,
pub product_name: u8,
pub version: u8,
pub serial_number: u8,
pub uuid: [u8; 16usize],
pub wake_up_type: u8,
pub sku: u8,
pub family: u8,
}
impl Clone for SmbiosSysInfo {
fn clone(&self) -> Self {
*self
}
}
unsafe impl ByteValued for SmbiosSysInfo {}
fn write_and_incr<T: ByteValued>(
mem: &GuestMemoryMmap,
val: T,
mut curptr: GuestAddress,
) -> Result<GuestAddress> {
mem.write_obj(val, curptr).map_err(|_| Error::WriteData)?;
curptr = curptr
.checked_add(mem::size_of::<T>() as u64)
.ok_or(Error::NotEnoughMemory)?;
Ok(curptr)
}
fn write_string(
mem: &GuestMemoryMmap,
val: &str,
mut curptr: GuestAddress,
) -> Result<GuestAddress> {
for c in val.as_bytes().iter() {
curptr = write_and_incr(mem, *c, curptr)?;
}
curptr = write_and_incr(mem, 0u8, curptr)?;
Ok(curptr)
}
pub fn setup_smbios(mem: &GuestMemoryMmap) -> Result<u64> {
let physptr = GuestAddress(SMBIOS_START)
.checked_add(mem::size_of::<Smbios30Entrypoint>() as u64)
.ok_or(Error::NotEnoughMemory)?;
let mut curptr = physptr;
let mut handle = 0;
{
handle += 1;
let smbios_biosinfo = SmbiosBiosInfo {
typ: BIOS_INFORMATION,
length: mem::size_of::<SmbiosBiosInfo>() as u8,
handle,
vendor: 1, // First string written in this section
version: 2, // Second string written in this section
characteristics: PCI_SUPPORTED,
characteristics_ext2: IS_VIRTUAL_MACHINE,
..Default::default()
};
curptr = write_and_incr(mem, smbios_biosinfo, curptr)?;
curptr = write_string(mem, "cloud-hypervisor", curptr)?;
curptr = write_string(mem, "0", curptr)?;
curptr = write_and_incr(mem, 0u8, curptr)?;
}
{
handle += 1;
let smbios_sysinfo = SmbiosSysInfo {
typ: SYSTEM_INFORMATION,
length: mem::size_of::<SmbiosSysInfo>() as u8,
handle,
manufacturer: 1, // First string written in this section
product_name: 2, // Second string written in this section
..Default::default()
};
curptr = write_and_incr(mem, smbios_sysinfo, curptr)?;
curptr = write_string(mem, "Cloud Hypervisor", curptr)?;
curptr = write_string(mem, "cloud-hypervisor", curptr)?;
curptr = write_and_incr(mem, 0u8, curptr)?;
}
{
handle += 1;
let smbios_sysinfo = SmbiosSysInfo {
typ: END_OF_TABLE,
length: mem::size_of::<SmbiosSysInfo>() as u8,
handle,
..Default::default()
};
curptr = write_and_incr(mem, smbios_sysinfo, curptr)?;
curptr = write_and_incr(mem, 0u8, curptr)?;
}
{
let mut smbios_ep = Smbios30Entrypoint {
signature: *SM3_MAGIC_IDENT,
length: mem::size_of::<Smbios30Entrypoint>() as u8,
// SMBIOS rev 3.2.0
majorver: 0x03,
minorver: 0x02,
docrev: 0x00,
revision: 0x01, // SMBIOS 3.0
max_size: curptr.unchecked_offset_from(physptr) as u32,
physptr: physptr.0,
..Default::default()
};
smbios_ep.checksum = compute_checksum(&smbios_ep);
mem.write_obj(smbios_ep, GuestAddress(SMBIOS_START))
.map_err(|_| Error::WriteSmbiosEp)?;
}
Ok(curptr.unchecked_offset_from(physptr))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn struct_size() {
assert_eq!(
mem::size_of::<Smbios30Entrypoint>(),
0x18usize,
concat!("Size of: ", stringify!(Smbios30Entrypoint))
);
assert_eq!(
mem::size_of::<SmbiosBiosInfo>(),
0x14usize,
concat!("Size of: ", stringify!(SmbiosBiosInfo))
);
assert_eq!(
mem::size_of::<SmbiosSysInfo>(),
0x1busize,
concat!("Size of: ", stringify!(SmbiosSysInfo))
);
}
#[test]
fn entrypoint_checksum() {
let mem = GuestMemoryMmap::from_ranges(&[(GuestAddress(SMBIOS_START), 4096)]).unwrap();
setup_smbios(&mem).unwrap();
let smbios_ep: Smbios30Entrypoint = mem.read_obj(GuestAddress(SMBIOS_START)).unwrap();
assert_eq!(compute_checksum(&smbios_ep), 0);
}
}

318
arch/src/x86_64/tdx/mod.rs Normal file
View File

@@ -0,0 +1,318 @@
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use thiserror::Error;
use vm_memory::{ByteValued, Bytes, GuestAddress, GuestMemoryError, GuestMemoryMmap};
#[derive(Error, Debug)]
pub enum TdvfError {
#[error("Failed read TDVF descriptor: {0}")]
ReadDescriptor(#[source] std::io::Error),
#[error("Failed read TDVF descriptor offset: {0}")]
ReadDescriptorOffset(#[source] std::io::Error),
#[error("Invalid descriptor signature")]
InvalidDescriptorSignature,
#[error("Invalid descriptor size")]
InvalidDescriptorSize,
#[error("Invalid descriptor version")]
InvalidDescriptorVersion,
#[error("Failed to write HOB details to guest memory: {0}")]
GuestMemoryWriteHob(#[source] GuestMemoryError),
}
// TDVF_DESCRIPTOR
#[repr(packed)]
pub struct TdvfDescriptor {
signature: [u8; 4],
length: u32,
version: u32,
num_sections: u32, // NumberOfSectionEntry
}
// TDVF_SECTION
#[repr(packed)]
#[derive(Clone, Copy, Default, Debug)]
pub struct TdvfSection {
pub data_offset: u32,
pub data_size: u32, // RawDataSize
pub address: u64, // MemoryAddress
pub size: u64, // MemoryDataSize
pub r#type: TdvfSectionType,
pub attributes: u32,
}
#[repr(u32)]
#[derive(Clone, Copy, Debug)]
pub enum TdvfSectionType {
Bfv,
Cfv,
TdHob,
TempMem,
Reserved = 0xffffffff,
}
impl Default for TdvfSectionType {
fn default() -> Self {
TdvfSectionType::Reserved
}
}
pub fn parse_tdvf_sections(file: &mut File) -> Result<Vec<TdvfSection>, TdvfError> {
// The 32-bit offset to the TDVF metadata is located 32 bytes from
// the end of the file.
// See "TDVF Metadata Pointer" in "TDX Virtual Firmware Design Guide
file.seek(SeekFrom::End(-0x20))
.map_err(TdvfError::ReadDescriptorOffset)?;
let mut descriptor_offset: [u8; 4] = [0; 4];
file.read_exact(&mut descriptor_offset)
.map_err(TdvfError::ReadDescriptorOffset)?;
let descriptor_offset = u32::from_le_bytes(descriptor_offset) as u64;
file.seek(SeekFrom::Start(descriptor_offset))
.map_err(TdvfError::ReadDescriptor)?;
let mut descriptor: TdvfDescriptor = unsafe { std::mem::zeroed() };
// Safe as we read exactly the size of the descriptor header
file.read_exact(unsafe {
std::slice::from_raw_parts_mut(
&mut descriptor as *mut _ as *mut u8,
std::mem::size_of::<TdvfDescriptor>(),
)
})
.map_err(TdvfError::ReadDescriptor)?;
if &descriptor.signature != b"TDVF" {
return Err(TdvfError::InvalidDescriptorSignature);
}
if descriptor.length as usize
!= std::mem::size_of::<TdvfDescriptor>()
+ std::mem::size_of::<TdvfSection>() * descriptor.num_sections as usize
{
return Err(TdvfError::InvalidDescriptorSize);
}
if descriptor.version != 1 {
return Err(TdvfError::InvalidDescriptorVersion);
}
let mut sections = Vec::new();
sections.resize_with(descriptor.num_sections as usize, TdvfSection::default);
// Safe as we read exactly the advertised sections
file.read_exact(unsafe {
std::slice::from_raw_parts_mut(
sections.as_mut_ptr() as *mut u8,
descriptor.num_sections as usize * std::mem::size_of::<TdvfSection>(),
)
})
.map_err(TdvfError::ReadDescriptor)?;
Ok(sections)
}
#[repr(u16)]
#[derive(Copy, Clone, Debug)]
enum HobType {
Handoff = 0x1,
ResourceDescriptor = 0x3,
Unused = 0xfffe,
EndOfHobList = 0xffff,
}
impl Default for HobType {
fn default() -> Self {
HobType::Unused
}
}
#[repr(C)]
#[derive(Copy, Clone, Default, Debug)]
struct HobHeader {
r#type: HobType,
length: u16,
reserved: u32,
}
unsafe impl ByteValued for HobHeader {}
#[repr(C)]
#[derive(Copy, Clone, Default, Debug)]
struct HobHandoffInfoTable {
header: HobHeader,
version: u32,
efi_memory_top: u64,
efi_memory_bottom: u64,
efi_free_memory_top: u64,
efi_free_memory_bottom: u64,
efi_end_of_hob_list: u64,
}
unsafe impl ByteValued for HobHandoffInfoTable {}
#[repr(C)]
#[derive(Copy, Clone, Default, Debug)]
struct EfiGuid {
data1: u32,
data2: u16,
data3: u16,
data4: [u8; 8],
}
#[repr(C)]
#[derive(Copy, Clone, Default, Debug)]
struct HobResourceDescriptor {
header: HobHeader,
owner: EfiGuid,
resource_type: u32,
resource_attribute: u32,
physical_start: u64,
resource_length: u64,
}
unsafe impl ByteValued for HobResourceDescriptor {}
pub struct TdHob {
start_offset: u64,
current_offset: u64,
}
fn align_hob(v: u64) -> u64 {
(v + 7) / 8 * 8
}
impl TdHob {
fn update_offset<T>(&mut self) {
self.current_offset = align_hob(self.current_offset + std::mem::size_of::<T>() as u64)
}
pub fn start(offset: u64) -> TdHob {
// Leave a gap to place the HandoffTable at the start as it can only be filled in later
let mut hob = TdHob {
start_offset: offset,
current_offset: offset,
};
hob.update_offset::<HobHandoffInfoTable>();
hob
}
pub fn finish(&mut self, mem: &GuestMemoryMmap) -> Result<(), TdvfError> {
// Write end
let end = HobHeader {
r#type: HobType::EndOfHobList,
length: std::mem::size_of::<HobHeader>() as u16,
reserved: 0,
};
info!("Writing HOB end {:x} {:x?}", self.current_offset, end);
mem.write_obj(end, GuestAddress(self.current_offset))
.map_err(TdvfError::GuestMemoryWriteHob)?;
self.update_offset::<HobHeader>();
// Write handoff, delayed as it needs end of HOB list
let efi_end_of_hob_list = self.current_offset;
let handoff = HobHandoffInfoTable {
header: HobHeader {
r#type: HobType::Handoff,
length: std::mem::size_of::<HobHandoffInfoTable>() as u16,
reserved: 0,
},
version: 0x9,
efi_memory_top: 0,
efi_memory_bottom: 0,
efi_free_memory_top: 0,
efi_free_memory_bottom: 0,
efi_end_of_hob_list,
};
info!("Writing HOB start {:x} {:x?}", self.start_offset, handoff);
mem.write_obj(handoff, GuestAddress(self.start_offset))
.map_err(TdvfError::GuestMemoryWriteHob)
}
pub fn add_resource(
&mut self,
mem: &GuestMemoryMmap,
physical_start: u64,
resource_length: u64,
resource_type: u32,
resource_attribute: u32,
) -> Result<(), TdvfError> {
let resource_descriptor = HobResourceDescriptor {
header: HobHeader {
r#type: HobType::ResourceDescriptor,
length: std::mem::size_of::<HobResourceDescriptor>() as u16,
reserved: 0,
},
owner: EfiGuid::default(),
resource_type,
resource_attribute,
physical_start,
resource_length,
};
info!(
"Writing HOB resource {:x} {:x?}",
self.current_offset, resource_descriptor
);
mem.write_obj(resource_descriptor, GuestAddress(self.current_offset))
.map_err(TdvfError::GuestMemoryWriteHob)?;
self.update_offset::<HobResourceDescriptor>();
Ok(())
}
pub fn add_memory_resource(
&mut self,
mem: &GuestMemoryMmap,
physical_start: u64,
resource_length: u64,
ram: bool,
) -> Result<(), TdvfError> {
self.add_resource(
mem,
physical_start,
resource_length,
if ram {
0 /* EFI_RESOURCE_SYSTEM_MEMORY */
} else {
0x5 /*EFI_RESOURCE_MEMORY_RESERVED */
},
/* TODO:
* QEMU currently fills it in like this:
* EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED
* which differs from the spec (due to TDVF implementation issue?)
*/
0x7,
)
}
pub fn add_mmio_resource(
&mut self,
mem: &GuestMemoryMmap,
physical_start: u64,
resource_length: u64,
) -> Result<(), TdvfError> {
self.add_resource(
mem,
physical_start,
resource_length,
0x1, /* EFI_RESOURCE_MEMORY_MAPPED_IO */
/*
* EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
*/
0x403,
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[ignore]
fn test_parse_tdvf_sections() {
let mut f = std::fs::File::open("tdvf.fd").unwrap();
let sections = parse_tdvf_sections(&mut f).unwrap();
for section in sections {
eprintln!("{:x?}", section)
}
}
}

View File

@@ -8,18 +8,7 @@
#[allow(non_upper_case_globals)]
#[allow(non_camel_case_types)]
#[allow(non_snake_case)]
#[allow(
clippy::unreadable_literal,
clippy::redundant_static_lifetimes,
clippy::trivially_copy_pass_by_ref,
clippy::useless_transmute,
clippy::should_implement_trait,
clippy::transmute_ptr_to_ptr
)]
#[allow(non_camel_case_types)]
#[allow(non_upper_case_globals)]
#[allow(clippy::unreadable_literal, clippy::redundant_static_lifetimes)]
pub mod mpspec;
#[allow(non_upper_case_globals)]
#[allow(clippy::unreadable_literal, clippy::redundant_static_lifetimes)]
pub mod msr_index;

View File

@@ -67,7 +67,7 @@ fn bindgen_test_layout_mpf_intel() {
concat!("Alignment of ", stringify!(mpf_intel))
);
assert_eq!(
unsafe { &(*(0 as *const mpf_intel)).signature as *const _ as usize },
unsafe { &(*std::ptr::null::<mpf_intel>()).signature as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
@@ -77,7 +77,7 @@ fn bindgen_test_layout_mpf_intel() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpf_intel)).physptr as *const _ as usize },
unsafe { &(*std::ptr::null::<mpf_intel>()).physptr as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
@@ -87,7 +87,7 @@ fn bindgen_test_layout_mpf_intel() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpf_intel)).length as *const _ as usize },
unsafe { &(*std::ptr::null::<mpf_intel>()).length as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",
@@ -97,7 +97,7 @@ fn bindgen_test_layout_mpf_intel() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpf_intel)).specification as *const _ as usize },
unsafe { &(*std::ptr::null::<mpf_intel>()).specification as *const _ as usize },
9usize,
concat!(
"Alignment of field: ",
@@ -107,7 +107,7 @@ fn bindgen_test_layout_mpf_intel() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpf_intel)).checksum as *const _ as usize },
unsafe { &(*std::ptr::null::<mpf_intel>()).checksum as *const _ as usize },
10usize,
concat!(
"Alignment of field: ",
@@ -117,7 +117,7 @@ fn bindgen_test_layout_mpf_intel() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpf_intel)).feature1 as *const _ as usize },
unsafe { &(*std::ptr::null::<mpf_intel>()).feature1 as *const _ as usize },
11usize,
concat!(
"Alignment of field: ",
@@ -127,7 +127,7 @@ fn bindgen_test_layout_mpf_intel() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpf_intel)).feature2 as *const _ as usize },
unsafe { &(*std::ptr::null::<mpf_intel>()).feature2 as *const _ as usize },
12usize,
concat!(
"Alignment of field: ",
@@ -137,7 +137,7 @@ fn bindgen_test_layout_mpf_intel() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpf_intel)).feature3 as *const _ as usize },
unsafe { &(*std::ptr::null::<mpf_intel>()).feature3 as *const _ as usize },
13usize,
concat!(
"Alignment of field: ",
@@ -147,7 +147,7 @@ fn bindgen_test_layout_mpf_intel() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpf_intel)).feature4 as *const _ as usize },
unsafe { &(*std::ptr::null::<mpf_intel>()).feature4 as *const _ as usize },
14usize,
concat!(
"Alignment of field: ",
@@ -157,7 +157,7 @@ fn bindgen_test_layout_mpf_intel() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpf_intel)).feature5 as *const _ as usize },
unsafe { &(*std::ptr::null::<mpf_intel>()).feature5 as *const _ as usize },
15usize,
concat!(
"Alignment of field: ",
@@ -200,7 +200,7 @@ fn bindgen_test_layout_mpc_table() {
concat!("Alignment of ", stringify!(mpc_table))
);
assert_eq!(
unsafe { &(*(0 as *const mpc_table)).signature as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_table>()).signature as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
@@ -210,7 +210,7 @@ fn bindgen_test_layout_mpc_table() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_table)).length as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_table>()).length as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
@@ -220,7 +220,7 @@ fn bindgen_test_layout_mpc_table() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_table)).spec as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_table>()).spec as *const _ as usize },
6usize,
concat!(
"Alignment of field: ",
@@ -230,7 +230,7 @@ fn bindgen_test_layout_mpc_table() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_table)).checksum as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_table>()).checksum as *const _ as usize },
7usize,
concat!(
"Alignment of field: ",
@@ -240,7 +240,7 @@ fn bindgen_test_layout_mpc_table() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_table)).oem as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_table>()).oem as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",
@@ -250,7 +250,7 @@ fn bindgen_test_layout_mpc_table() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_table)).productid as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_table>()).productid as *const _ as usize },
16usize,
concat!(
"Alignment of field: ",
@@ -260,7 +260,7 @@ fn bindgen_test_layout_mpc_table() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_table)).oemptr as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_table>()).oemptr as *const _ as usize },
28usize,
concat!(
"Alignment of field: ",
@@ -270,7 +270,7 @@ fn bindgen_test_layout_mpc_table() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_table)).oemsize as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_table>()).oemsize as *const _ as usize },
32usize,
concat!(
"Alignment of field: ",
@@ -280,7 +280,7 @@ fn bindgen_test_layout_mpc_table() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_table)).oemcount as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_table>()).oemcount as *const _ as usize },
34usize,
concat!(
"Alignment of field: ",
@@ -290,7 +290,7 @@ fn bindgen_test_layout_mpc_table() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_table)).lapic as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_table>()).lapic as *const _ as usize },
36usize,
concat!(
"Alignment of field: ",
@@ -300,7 +300,7 @@ fn bindgen_test_layout_mpc_table() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_table)).reserved as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_table>()).reserved as *const _ as usize },
40usize,
concat!(
"Alignment of field: ",
@@ -339,7 +339,7 @@ fn bindgen_test_layout_mpc_cpu() {
concat!("Alignment of ", stringify!(mpc_cpu))
);
assert_eq!(
unsafe { &(*(0 as *const mpc_cpu)).type_ as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_cpu>()).type_ as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
@@ -349,7 +349,7 @@ fn bindgen_test_layout_mpc_cpu() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_cpu)).apicid as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_cpu>()).apicid as *const _ as usize },
1usize,
concat!(
"Alignment of field: ",
@@ -359,7 +359,7 @@ fn bindgen_test_layout_mpc_cpu() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_cpu)).apicver as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_cpu>()).apicver as *const _ as usize },
2usize,
concat!(
"Alignment of field: ",
@@ -369,7 +369,7 @@ fn bindgen_test_layout_mpc_cpu() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_cpu)).cpuflag as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_cpu>()).cpuflag as *const _ as usize },
3usize,
concat!(
"Alignment of field: ",
@@ -379,7 +379,7 @@ fn bindgen_test_layout_mpc_cpu() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_cpu)).cpufeature as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_cpu>()).cpufeature as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
@@ -389,7 +389,7 @@ fn bindgen_test_layout_mpc_cpu() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_cpu)).featureflag as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_cpu>()).featureflag as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",
@@ -399,7 +399,7 @@ fn bindgen_test_layout_mpc_cpu() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_cpu)).reserved as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_cpu>()).reserved as *const _ as usize },
12usize,
concat!(
"Alignment of field: ",
@@ -434,7 +434,7 @@ fn bindgen_test_layout_mpc_bus() {
concat!("Alignment of ", stringify!(mpc_bus))
);
assert_eq!(
unsafe { &(*(0 as *const mpc_bus)).type_ as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_bus>()).type_ as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
@@ -444,7 +444,7 @@ fn bindgen_test_layout_mpc_bus() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_bus)).busid as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_bus>()).busid as *const _ as usize },
1usize,
concat!(
"Alignment of field: ",
@@ -454,7 +454,7 @@ fn bindgen_test_layout_mpc_bus() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_bus)).bustype as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_bus>()).bustype as *const _ as usize },
2usize,
concat!(
"Alignment of field: ",
@@ -491,7 +491,7 @@ fn bindgen_test_layout_mpc_ioapic() {
concat!("Alignment of ", stringify!(mpc_ioapic))
);
assert_eq!(
unsafe { &(*(0 as *const mpc_ioapic)).type_ as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_ioapic>()).type_ as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
@@ -501,7 +501,7 @@ fn bindgen_test_layout_mpc_ioapic() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_ioapic)).apicid as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_ioapic>()).apicid as *const _ as usize },
1usize,
concat!(
"Alignment of field: ",
@@ -511,7 +511,7 @@ fn bindgen_test_layout_mpc_ioapic() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_ioapic)).apicver as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_ioapic>()).apicver as *const _ as usize },
2usize,
concat!(
"Alignment of field: ",
@@ -521,7 +521,7 @@ fn bindgen_test_layout_mpc_ioapic() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_ioapic)).flags as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_ioapic>()).flags as *const _ as usize },
3usize,
concat!(
"Alignment of field: ",
@@ -531,7 +531,7 @@ fn bindgen_test_layout_mpc_ioapic() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_ioapic)).apicaddr as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_ioapic>()).apicaddr as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
@@ -570,7 +570,7 @@ fn bindgen_test_layout_mpc_intsrc() {
concat!("Alignment of ", stringify!(mpc_intsrc))
);
assert_eq!(
unsafe { &(*(0 as *const mpc_intsrc)).type_ as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_intsrc>()).type_ as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
@@ -580,7 +580,7 @@ fn bindgen_test_layout_mpc_intsrc() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_intsrc)).irqtype as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_intsrc>()).irqtype as *const _ as usize },
1usize,
concat!(
"Alignment of field: ",
@@ -590,7 +590,7 @@ fn bindgen_test_layout_mpc_intsrc() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_intsrc)).irqflag as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_intsrc>()).irqflag as *const _ as usize },
2usize,
concat!(
"Alignment of field: ",
@@ -600,7 +600,7 @@ fn bindgen_test_layout_mpc_intsrc() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_intsrc)).srcbus as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_intsrc>()).srcbus as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
@@ -610,7 +610,7 @@ fn bindgen_test_layout_mpc_intsrc() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_intsrc)).srcbusirq as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_intsrc>()).srcbusirq as *const _ as usize },
5usize,
concat!(
"Alignment of field: ",
@@ -620,7 +620,7 @@ fn bindgen_test_layout_mpc_intsrc() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_intsrc)).dstapic as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_intsrc>()).dstapic as *const _ as usize },
6usize,
concat!(
"Alignment of field: ",
@@ -630,7 +630,7 @@ fn bindgen_test_layout_mpc_intsrc() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_intsrc)).dstirq as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_intsrc>()).dstirq as *const _ as usize },
7usize,
concat!(
"Alignment of field: ",
@@ -674,7 +674,7 @@ fn bindgen_test_layout_mpc_lintsrc() {
concat!("Alignment of ", stringify!(mpc_lintsrc))
);
assert_eq!(
unsafe { &(*(0 as *const mpc_lintsrc)).type_ as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).type_ as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
@@ -684,7 +684,7 @@ fn bindgen_test_layout_mpc_lintsrc() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_lintsrc)).irqtype as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).irqtype as *const _ as usize },
1usize,
concat!(
"Alignment of field: ",
@@ -694,7 +694,7 @@ fn bindgen_test_layout_mpc_lintsrc() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_lintsrc)).irqflag as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).irqflag as *const _ as usize },
2usize,
concat!(
"Alignment of field: ",
@@ -704,7 +704,7 @@ fn bindgen_test_layout_mpc_lintsrc() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_lintsrc)).srcbusid as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).srcbusid as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
@@ -714,7 +714,7 @@ fn bindgen_test_layout_mpc_lintsrc() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_lintsrc)).srcbusirq as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).srcbusirq as *const _ as usize },
5usize,
concat!(
"Alignment of field: ",
@@ -724,7 +724,7 @@ fn bindgen_test_layout_mpc_lintsrc() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_lintsrc)).destapic as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).destapic as *const _ as usize },
6usize,
concat!(
"Alignment of field: ",
@@ -734,7 +734,7 @@ fn bindgen_test_layout_mpc_lintsrc() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_lintsrc)).destapiclint as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).destapiclint as *const _ as usize },
7usize,
concat!(
"Alignment of field: ",
@@ -771,7 +771,7 @@ fn bindgen_test_layout_mpc_oemtable() {
concat!("Alignment of ", stringify!(mpc_oemtable))
);
assert_eq!(
unsafe { &(*(0 as *const mpc_oemtable)).signature as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_oemtable>()).signature as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
@@ -781,7 +781,7 @@ fn bindgen_test_layout_mpc_oemtable() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_oemtable)).length as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_oemtable>()).length as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
@@ -791,7 +791,7 @@ fn bindgen_test_layout_mpc_oemtable() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_oemtable)).rev as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_oemtable>()).rev as *const _ as usize },
6usize,
concat!(
"Alignment of field: ",
@@ -801,7 +801,7 @@ fn bindgen_test_layout_mpc_oemtable() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_oemtable)).checksum as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_oemtable>()).checksum as *const _ as usize },
7usize,
concat!(
"Alignment of field: ",
@@ -811,7 +811,7 @@ fn bindgen_test_layout_mpc_oemtable() {
)
);
assert_eq!(
unsafe { &(*(0 as *const mpc_oemtable)).mpc as *const _ as usize },
unsafe { &(*std::ptr::null::<mpc_oemtable>()).mpc as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",

24
block_util/Cargo.toml Normal file
View File

@@ -0,0 +1,24 @@
[package]
name = "block_util"
version = "0.1.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2018"
[features]
default = []
io_uring = []
[dependencies]
io-uring = ">=0.4.0"
libc = "0.2.91"
log = "0.4.14"
qcow = { path = "../qcow" }
serde = ">=1.0.27"
serde_derive = ">=1.0.27"
serde_json = ">=1.0.9"
thiserror = "1.0"
virtio-bindings = { version = "0.1", features = ["virtio-v5_0_0"]}
vm-memory = { version = "0.5.0", features = ["backend-mmap", "backend-atomic"] }
vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = ">=0.3.1"

View File

@@ -0,0 +1,56 @@
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use thiserror::Error;
use vmm_sys_util::eventfd::EventFd;
#[derive(Error, Debug)]
pub enum DiskFileError {
/// Failed getting disk file size.
#[error("Failed getting disk file size: {0}")]
Size(#[source] std::io::Error),
/// Failed creating a new AsyncIo.
#[error("Failed creating a new AsyncIo: {0}")]
NewAsyncIo(#[source] std::io::Error),
}
pub type DiskFileResult<T> = std::result::Result<T, DiskFileError>;
pub trait DiskFile: Send + Sync {
fn size(&mut self) -> DiskFileResult<u64>;
fn new_async_io(&self, ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>>;
}
#[derive(Error, Debug)]
pub enum AsyncIoError {
/// Failed vectored reading from file.
#[error("Failed vectored reading from file: {0}")]
ReadVectored(#[source] std::io::Error),
/// Failed vectored writing to file.
#[error("Failed vectored writing to file: {0}")]
WriteVectored(#[source] std::io::Error),
/// Failed synchronizing file.
#[error("Failed synchronizing file: {0}")]
Fsync(#[source] std::io::Error),
}
pub type AsyncIoResult<T> = std::result::Result<T, AsyncIoError>;
pub trait AsyncIo: Send + Sync {
fn notifier(&self) -> &EventFd;
fn read_vectored(
&mut self,
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
) -> AsyncIoResult<()>;
fn write_vectored(
&mut self,
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
) -> AsyncIoResult<()>;
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()>;
fn complete(&mut self) -> Vec<(u64, i32)>;
}

View File

@@ -0,0 +1,110 @@
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
};
use crate::raw_async::RawFileAsync;
use crate::vhd::VhdFooter;
use std::fs::File;
use std::os::unix::io::{AsRawFd, RawFd};
use vmm_sys_util::eventfd::EventFd;
pub struct FixedVhdDiskAsync {
file: File,
size: u64,
}
impl FixedVhdDiskAsync {
pub fn new(mut file: File) -> std::io::Result<Self> {
let footer = VhdFooter::new(&mut file)?;
Ok(FixedVhdDiskAsync {
file,
size: footer.current_size(),
})
}
}
impl DiskFile for FixedVhdDiskAsync {
fn size(&mut self) -> DiskFileResult<u64> {
Ok(self.size)
}
fn new_async_io(&self, ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
Ok(Box::new(
FixedVhdAsync::new(self.file.as_raw_fd(), ring_depth, self.size)
.map_err(DiskFileError::NewAsyncIo)?,
) as Box<dyn AsyncIo>)
}
}
pub struct FixedVhdAsync {
raw_file_async: RawFileAsync,
size: u64,
}
impl FixedVhdAsync {
pub fn new(fd: RawFd, ring_depth: u32, size: u64) -> std::io::Result<Self> {
let raw_file_async = RawFileAsync::new(fd, ring_depth)?;
Ok(FixedVhdAsync {
raw_file_async,
size,
})
}
}
impl AsyncIo for FixedVhdAsync {
fn notifier(&self) -> &EventFd {
self.raw_file_async.notifier()
}
fn read_vectored(
&mut self,
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
) -> AsyncIoResult<()> {
if offset as u64 >= self.size {
return Err(AsyncIoError::ReadVectored(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!(
"Invalid offset {}, can't be larger than file size {}",
offset, self.size
),
)));
}
self.raw_file_async.read_vectored(offset, iovecs, user_data)
}
fn write_vectored(
&mut self,
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
) -> AsyncIoResult<()> {
if offset as u64 >= self.size {
return Err(AsyncIoError::WriteVectored(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!(
"Invalid offset {}, can't be larger than file size {}",
offset, self.size
),
)));
}
self.raw_file_async
.write_vectored(offset, iovecs, user_data)
}
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> {
self.raw_file_async.fsync(user_data)
}
fn complete(&mut self) -> Vec<(u64, i32)> {
self.raw_file_async.complete()
}
}

View File

@@ -0,0 +1,107 @@
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
};
use crate::raw_sync::RawFileSync;
use crate::vhd::VhdFooter;
use std::fs::File;
use std::os::unix::io::{AsRawFd, RawFd};
use vmm_sys_util::eventfd::EventFd;
pub struct FixedVhdDiskSync {
file: File,
size: u64,
}
impl FixedVhdDiskSync {
pub fn new(mut file: File) -> std::io::Result<Self> {
let footer = VhdFooter::new(&mut file)?;
Ok(FixedVhdDiskSync {
file,
size: footer.current_size(),
})
}
}
impl DiskFile for FixedVhdDiskSync {
fn size(&mut self) -> DiskFileResult<u64> {
Ok(self.size)
}
fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
Ok(Box::new(
FixedVhdSync::new(self.file.as_raw_fd(), self.size)
.map_err(DiskFileError::NewAsyncIo)?,
) as Box<dyn AsyncIo>)
}
}
pub struct FixedVhdSync {
raw_file_sync: RawFileSync,
size: u64,
}
impl FixedVhdSync {
pub fn new(fd: RawFd, size: u64) -> std::io::Result<Self> {
Ok(FixedVhdSync {
raw_file_sync: RawFileSync::new(fd),
size,
})
}
}
impl AsyncIo for FixedVhdSync {
fn notifier(&self) -> &EventFd {
self.raw_file_sync.notifier()
}
fn read_vectored(
&mut self,
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
) -> AsyncIoResult<()> {
if offset as u64 >= self.size {
return Err(AsyncIoError::ReadVectored(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!(
"Invalid offset {}, can't be larger than file size {}",
offset, self.size
),
)));
}
self.raw_file_sync.read_vectored(offset, iovecs, user_data)
}
fn write_vectored(
&mut self,
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
) -> AsyncIoResult<()> {
if offset as u64 >= self.size {
return Err(AsyncIoError::WriteVectored(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!(
"Invalid offset {}, can't be larger than file size {}",
offset, self.size
),
)));
}
self.raw_file_sync.write_vectored(offset, iovecs, user_data)
}
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> {
self.raw_file_sync.fsync(user_data)
}
fn complete(&mut self) -> Vec<(u64, i32)> {
self.raw_file_sync.complete()
}
}

701
block_util/src/lib.rs Normal file
View File

@@ -0,0 +1,701 @@
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
//
// Copyright © 2020 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
pub mod async_io;
pub mod fixed_vhd_async;
pub mod fixed_vhd_sync;
pub mod qcow_sync;
pub mod raw_async;
pub mod raw_sync;
pub mod vhd;
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult, DiskFileError, DiskFileResult};
#[cfg(feature = "io_uring")]
use io_uring::{opcode, IoUring, Probe};
use serde::ser::{Serialize, SerializeStruct, Serializer};
use std::cmp;
use std::convert::TryInto;
use std::fs::File;
use std::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
use std::os::linux::fs::MetadataExt;
#[cfg(feature = "io_uring")]
use std::os::unix::io::AsRawFd;
use std::path::Path;
use std::result;
use std::sync::{Arc, Mutex};
use virtio_bindings::bindings::virtio_blk::*;
use vm_memory::{ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryError, GuestMemoryMmap};
use vm_virtio::DescriptorChain;
use vmm_sys_util::eventfd::EventFd;
const SECTOR_SHIFT: u8 = 9;
pub const SECTOR_SIZE: u64 = 0x01 << SECTOR_SHIFT;
#[derive(Debug)]
pub enum Error {
/// Guest gave us bad memory addresses.
GuestMemory(GuestMemoryError),
/// Guest gave us offsets that would have overflowed a usize.
CheckedOffset(GuestAddress, usize),
/// Guest gave us a write only descriptor that protocol says to read from.
UnexpectedWriteOnlyDescriptor,
/// Guest gave us a read only descriptor that protocol says to write to.
UnexpectedReadOnlyDescriptor,
/// Guest gave us too few descriptors in a descriptor chain.
DescriptorChainTooShort,
/// Guest gave us a descriptor that was too short to use.
DescriptorLengthTooSmall,
/// Getting a block's metadata fails for any reason.
GetFileMetadata,
/// The requested operation would cause a seek beyond disk end.
InvalidOffset,
/// The requested operation does not support multiple descriptors.
TooManyDescriptors,
}
fn build_device_id(disk_path: &Path) -> result::Result<String, Error> {
let blk_metadata = match disk_path.metadata() {
Err(_) => return Err(Error::GetFileMetadata),
Ok(m) => m,
};
// This is how kvmtool does it.
let device_id = format!(
"{}{}{}",
blk_metadata.st_dev(),
blk_metadata.st_rdev(),
blk_metadata.st_ino()
);
Ok(device_id)
}
pub fn build_disk_image_id(disk_path: &Path) -> Vec<u8> {
let mut default_disk_image_id = vec![0; VIRTIO_BLK_ID_BYTES as usize];
match build_device_id(disk_path) {
Err(_) => {
warn!("Could not generate device id. We'll use a default.");
}
Ok(m) => {
// The kernel only knows to read a maximum of VIRTIO_BLK_ID_BYTES.
// This will also zero out any leftover bytes.
let disk_id = m.as_bytes();
let bytes_to_copy = cmp::min(disk_id.len(), VIRTIO_BLK_ID_BYTES as usize);
default_disk_image_id[..bytes_to_copy].clone_from_slice(&disk_id[..bytes_to_copy])
}
}
default_disk_image_id
}
#[derive(Debug)]
pub enum ExecuteError {
BadRequest(Error),
Flush(io::Error),
Read(GuestMemoryError),
Seek(io::Error),
Write(GuestMemoryError),
Unsupported(u32),
SubmitIoUring(io::Error),
GetHostAddress(GuestMemoryError),
AsyncRead(AsyncIoError),
AsyncWrite(AsyncIoError),
AsyncFlush(AsyncIoError),
}
impl ExecuteError {
pub fn status(&self) -> u32 {
match *self {
ExecuteError::BadRequest(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Flush(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Read(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Seek(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Write(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Unsupported(_) => VIRTIO_BLK_S_UNSUPP,
ExecuteError::SubmitIoUring(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::GetHostAddress(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::AsyncRead(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::AsyncWrite(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::AsyncFlush(_) => VIRTIO_BLK_S_IOERR,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum RequestType {
In,
Out,
Flush,
GetDeviceId,
Unsupported(u32),
}
pub fn request_type(
mem: &GuestMemoryMmap,
desc_addr: GuestAddress,
) -> result::Result<RequestType, Error> {
let type_ = mem.read_obj(desc_addr).map_err(Error::GuestMemory)?;
match type_ {
VIRTIO_BLK_T_IN => Ok(RequestType::In),
VIRTIO_BLK_T_OUT => Ok(RequestType::Out),
VIRTIO_BLK_T_FLUSH => Ok(RequestType::Flush),
VIRTIO_BLK_T_GET_ID => Ok(RequestType::GetDeviceId),
t => Ok(RequestType::Unsupported(t)),
}
}
fn sector(mem: &GuestMemoryMmap, desc_addr: GuestAddress) -> result::Result<u64, Error> {
const SECTOR_OFFSET: usize = 8;
let addr = match mem.checked_offset(desc_addr, SECTOR_OFFSET) {
Some(v) => v,
None => return Err(Error::CheckedOffset(desc_addr, SECTOR_OFFSET)),
};
mem.read_obj(addr).map_err(Error::GuestMemory)
}
#[derive(Debug)]
pub struct Request {
pub request_type: RequestType,
pub sector: u64,
pub data_descriptors: Vec<(GuestAddress, u32)>,
pub status_addr: GuestAddress,
pub writeback: bool,
}
impl Request {
pub fn parse(
avail_desc: &DescriptorChain,
mem: &GuestMemoryMmap,
) -> result::Result<Request, Error> {
// The head contains the request type which MUST be readable.
if avail_desc.is_write_only() {
return Err(Error::UnexpectedWriteOnlyDescriptor);
}
let mut req = Request {
request_type: request_type(&mem, avail_desc.addr)?,
sector: sector(&mem, avail_desc.addr)?,
data_descriptors: Vec::new(),
status_addr: GuestAddress(0),
writeback: true,
};
let status_desc;
let mut desc = avail_desc
.next_descriptor()
.ok_or(Error::DescriptorChainTooShort)
.map_err(|e| {
error!("Only head descriptor present: request = {:?}", req);
e
})?;
if !desc.has_next() {
status_desc = desc;
// Only flush requests are allowed to skip the data descriptor.
if req.request_type != RequestType::Flush {
error!("Need a data descriptor: request = {:?}", req);
return Err(Error::DescriptorChainTooShort);
}
} else {
while desc.has_next() {
if desc.is_write_only() && req.request_type == RequestType::Out {
return Err(Error::UnexpectedWriteOnlyDescriptor);
}
if !desc.is_write_only() && req.request_type == RequestType::In {
return Err(Error::UnexpectedReadOnlyDescriptor);
}
if !desc.is_write_only() && req.request_type == RequestType::GetDeviceId {
return Err(Error::UnexpectedReadOnlyDescriptor);
}
req.data_descriptors.push((desc.addr, desc.len));
desc = desc
.next_descriptor()
.ok_or(Error::DescriptorChainTooShort)
.map_err(|e| {
error!("DescriptorChain corrupted: request = {:?}", req);
e
})?;
}
status_desc = desc;
}
// The status MUST always be writable.
if !status_desc.is_write_only() {
return Err(Error::UnexpectedReadOnlyDescriptor);
}
if status_desc.len < 1 {
return Err(Error::DescriptorLengthTooSmall);
}
req.status_addr = status_desc.addr;
Ok(req)
}
#[allow(clippy::ptr_arg)]
pub fn execute<T: Seek + Read + Write>(
&self,
disk: &mut T,
disk_nsectors: u64,
mem: &GuestMemoryMmap,
disk_id: &Vec<u8>,
) -> result::Result<u32, ExecuteError> {
disk.seek(SeekFrom::Start(self.sector << SECTOR_SHIFT))
.map_err(ExecuteError::Seek)?;
let mut len = 0;
for (data_addr, data_len) in &self.data_descriptors {
let mut top: u64 = u64::from(*data_len) / SECTOR_SIZE;
if u64::from(*data_len) % SECTOR_SIZE != 0 {
top += 1;
}
top = top
.checked_add(self.sector)
.ok_or(ExecuteError::BadRequest(Error::InvalidOffset))?;
if top > disk_nsectors {
return Err(ExecuteError::BadRequest(Error::InvalidOffset));
}
match self.request_type {
RequestType::In => {
mem.read_exact_from(*data_addr, disk, *data_len as usize)
.map_err(ExecuteError::Read)?;
len += data_len;
}
RequestType::Out => {
mem.write_all_to(*data_addr, disk, *data_len as usize)
.map_err(ExecuteError::Write)?;
if !self.writeback {
disk.flush().map_err(ExecuteError::Flush)?;
}
}
RequestType::Flush => disk.flush().map_err(ExecuteError::Flush)?,
RequestType::GetDeviceId => {
if (*data_len as usize) < disk_id.len() {
return Err(ExecuteError::BadRequest(Error::InvalidOffset));
}
mem.write_slice(&disk_id.as_slice(), *data_addr)
.map_err(ExecuteError::Write)?;
}
RequestType::Unsupported(t) => return Err(ExecuteError::Unsupported(t)),
};
}
Ok(len)
}
pub fn execute_async(
&self,
mem: &GuestMemoryMmap,
disk_nsectors: u64,
disk_image: &mut dyn AsyncIo,
disk_id: &[u8],
user_data: u64,
) -> result::Result<bool, ExecuteError> {
let sector = self.sector;
let request_type = self.request_type;
let offset = (sector << SECTOR_SHIFT) as libc::off_t;
let mut iovecs = Vec::new();
for (data_addr, data_len) in &self.data_descriptors {
let mut top: u64 = u64::from(*data_len) / SECTOR_SIZE;
if u64::from(*data_len) % SECTOR_SIZE != 0 {
top += 1;
}
top = top
.checked_add(sector)
.ok_or(ExecuteError::BadRequest(Error::InvalidOffset))?;
if top > disk_nsectors {
return Err(ExecuteError::BadRequest(Error::InvalidOffset));
}
let buf = mem
.get_slice(*data_addr, *data_len as usize)
.map_err(ExecuteError::GetHostAddress)?
.as_ptr();
let iovec = libc::iovec {
iov_base: buf as *mut libc::c_void,
iov_len: *data_len as libc::size_t,
};
iovecs.push(iovec);
}
// Queue operations expected to be submitted.
match request_type {
RequestType::In => {
disk_image
.read_vectored(offset, iovecs, user_data)
.map_err(ExecuteError::AsyncRead)?;
}
RequestType::Out => {
disk_image
.write_vectored(offset, iovecs, user_data)
.map_err(ExecuteError::AsyncWrite)?;
}
RequestType::Flush => {
disk_image
.fsync(Some(user_data))
.map_err(ExecuteError::AsyncFlush)?;
}
RequestType::GetDeviceId => {
let (data_addr, data_len) = if self.data_descriptors.len() == 1 {
(self.data_descriptors[0].0, self.data_descriptors[0].1)
} else {
return Err(ExecuteError::BadRequest(Error::TooManyDescriptors));
};
if (data_len as usize) < disk_id.len() {
return Err(ExecuteError::BadRequest(Error::InvalidOffset));
}
mem.write_slice(disk_id, data_addr)
.map_err(ExecuteError::Write)?;
return Ok(false);
}
RequestType::Unsupported(t) => return Err(ExecuteError::Unsupported(t)),
}
Ok(true)
}
pub fn set_writeback(&mut self, writeback: bool) {
self.writeback = writeback
}
}
#[derive(Copy, Clone, Debug, Default, Deserialize)]
#[repr(C, packed)]
pub struct VirtioBlockConfig {
pub capacity: u64,
pub size_max: u32,
pub seg_max: u32,
pub geometry: VirtioBlockGeometry,
pub blk_size: u32,
pub physical_block_exp: u8,
pub alignment_offset: u8,
pub min_io_size: u16,
pub opt_io_size: u32,
pub writeback: u8,
pub unused: u8,
pub num_queues: u16,
pub max_discard_sectors: u32,
pub max_discard_seg: u32,
pub discard_sector_alignment: u32,
pub max_write_zeroes_sectors: u32,
pub max_write_zeroes_seg: u32,
pub write_zeroes_may_unmap: u8,
pub unused1: [u8; 3],
}
// We must explicitly implement Serialize since the structure is packed and
// it's unsafe to borrow from a packed structure. And by default, if we derive
// Serialize from serde, it will borrow the values from the structure.
// That's why this implementation copies each field separately before it
// serializes the entire structure field by field.
impl Serialize for VirtioBlockConfig {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let capacity = self.capacity;
let size_max = self.size_max;
let seg_max = self.seg_max;
let geometry = self.geometry;
let blk_size = self.blk_size;
let physical_block_exp = self.physical_block_exp;
let alignment_offset = self.alignment_offset;
let min_io_size = self.min_io_size;
let opt_io_size = self.opt_io_size;
let writeback = self.writeback;
let unused = self.unused;
let num_queues = self.num_queues;
let max_discard_sectors = self.max_discard_sectors;
let max_discard_seg = self.max_discard_seg;
let discard_sector_alignment = self.discard_sector_alignment;
let max_write_zeroes_sectors = self.max_write_zeroes_sectors;
let max_write_zeroes_seg = self.max_write_zeroes_seg;
let write_zeroes_may_unmap = self.write_zeroes_may_unmap;
let unused1 = self.unused1;
let mut virtio_block_config = serializer.serialize_struct("VirtioBlockConfig", 60)?;
virtio_block_config.serialize_field("capacity", &capacity)?;
virtio_block_config.serialize_field("size_max", &size_max)?;
virtio_block_config.serialize_field("seg_max", &seg_max)?;
virtio_block_config.serialize_field("geometry", &geometry)?;
virtio_block_config.serialize_field("blk_size", &blk_size)?;
virtio_block_config.serialize_field("physical_block_exp", &physical_block_exp)?;
virtio_block_config.serialize_field("alignment_offset", &alignment_offset)?;
virtio_block_config.serialize_field("min_io_size", &min_io_size)?;
virtio_block_config.serialize_field("opt_io_size", &opt_io_size)?;
virtio_block_config.serialize_field("writeback", &writeback)?;
virtio_block_config.serialize_field("unused", &unused)?;
virtio_block_config.serialize_field("num_queues", &num_queues)?;
virtio_block_config.serialize_field("max_discard_sectors", &max_discard_sectors)?;
virtio_block_config.serialize_field("max_discard_seg", &max_discard_seg)?;
virtio_block_config
.serialize_field("discard_sector_alignment", &discard_sector_alignment)?;
virtio_block_config
.serialize_field("max_write_zeroes_sectors", &max_write_zeroes_sectors)?;
virtio_block_config.serialize_field("max_write_zeroes_seg", &max_write_zeroes_seg)?;
virtio_block_config.serialize_field("write_zeroes_may_unmap", &write_zeroes_may_unmap)?;
virtio_block_config.serialize_field("unused1", &unused1)?;
virtio_block_config.end()
}
}
unsafe impl ByteValued for VirtioBlockConfig {}
#[derive(Copy, Clone, Debug, Default, Deserialize)]
#[repr(C, packed)]
pub struct VirtioBlockGeometry {
pub cylinders: u16,
pub heads: u8,
pub sectors: u8,
}
// We must explicitly implement Serialize since the structure is packed and
// it's unsafe to borrow from a packed structure. And by default, if we derive
// Serialize from serde, it will borrow the values from the structure.
// That's why this implementation copies each field separately before it
// serializes the entire structure field by field.
impl Serialize for VirtioBlockGeometry {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let cylinders = self.cylinders;
let heads = self.heads;
let sectors = self.sectors;
let mut virtio_block_geometry = serializer.serialize_struct("VirtioBlockGeometry", 4)?;
virtio_block_geometry.serialize_field("cylinders", &cylinders)?;
virtio_block_geometry.serialize_field("heads", &heads)?;
virtio_block_geometry.serialize_field("sectors", &sectors)?;
virtio_block_geometry.end()
}
}
unsafe impl ByteValued for VirtioBlockGeometry {}
/// Check if io_uring for block device can be used on the current system, as
/// it correctly supports the expected io_uring features.
#[cfg(feature = "io_uring")]
pub fn block_io_uring_is_supported() -> bool {
let error_msg = "io_uring not supported:";
// Check we can create an io_uring instance, which effectively verifies
// that io_uring_setup() syscall is supported.
let io_uring = match IoUring::new(1) {
Ok(io_uring) => io_uring,
Err(e) => {
info!("{} failed to create io_uring instance: {}", error_msg, e);
return false;
}
};
let submitter = io_uring.submitter();
let event_fd = match EventFd::new(libc::EFD_NONBLOCK) {
Ok(fd) => fd,
Err(e) => {
info!("{} failed to create eventfd: {}", error_msg, e);
return false;
}
};
// Check we can register an eventfd as this is going to be needed while
// using io_uring with the virtio block device. This also validates that
// io_uring_register() syscall is supported.
match submitter.register_eventfd(event_fd.as_raw_fd()) {
Ok(_) => {}
Err(e) => {
info!("{} failed to register eventfd: {}", error_msg, e);
return false;
}
}
let mut probe = Probe::new();
// Check we can register a probe to validate supported operations.
match submitter.register_probe(&mut probe) {
Ok(_) => {}
Err(e) => {
info!("{} failed to register a probe: {}", error_msg, e);
return false;
}
}
// Check IORING_OP_FSYNC is supported
if !probe.is_supported(opcode::Fsync::CODE) {
info!("{} IORING_OP_FSYNC operation not supported", error_msg);
return false;
}
// Check IORING_OP_READ is supported
if !probe.is_supported(opcode::Read::CODE) {
info!("{} IORING_OP_READ operation not supported", error_msg);
return false;
}
// Check IORING_OP_WRITE is supported
if !probe.is_supported(opcode::Write::CODE) {
info!("{} IORING_OP_WRITE operation not supported", error_msg);
return false;
}
true
}
#[cfg(not(feature = "io_uring"))]
pub fn block_io_uring_is_supported() -> bool {
false
}
pub fn disk_size(file: &mut dyn Seek, semaphore: &mut Arc<Mutex<()>>) -> DiskFileResult<u64> {
// Take the semaphore to ensure other threads are not interacting with
// the underlying file.
let _lock = semaphore.lock().unwrap();
Ok(file.seek(SeekFrom::End(0)).map_err(DiskFileError::Size)? as u64)
}
pub trait ReadSeekFile: Read + Seek {}
impl<F: Read + Seek> ReadSeekFile for F {}
pub fn read_vectored_sync(
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
file: &mut dyn ReadSeekFile,
eventfd: &EventFd,
completion_list: &mut Vec<(u64, i32)>,
semaphore: &mut Arc<Mutex<()>>,
) -> AsyncIoResult<()> {
// Convert libc::iovec into IoSliceMut
let mut slices = Vec::new();
for iovec in iovecs.iter() {
slices.push(IoSliceMut::new(unsafe { std::mem::transmute(*iovec) }));
}
let result = {
// Take the semaphore to ensure other threads are not interacting
// with the underlying file.
let _lock = semaphore.lock().unwrap();
// Move the cursor to the right offset
file.seek(SeekFrom::Start(offset as u64))
.map_err(AsyncIoError::ReadVectored)?;
// Read vectored
file.read_vectored(slices.as_mut_slice())
.map_err(AsyncIoError::ReadVectored)?
};
completion_list.push((user_data, result as i32));
eventfd.write(1).unwrap();
Ok(())
}
pub trait WriteSeekFile: Write + Seek {}
impl<F: Write + Seek> WriteSeekFile for F {}
pub fn write_vectored_sync(
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
file: &mut dyn WriteSeekFile,
eventfd: &EventFd,
completion_list: &mut Vec<(u64, i32)>,
semaphore: &mut Arc<Mutex<()>>,
) -> AsyncIoResult<()> {
// Convert libc::iovec into IoSlice
let mut slices = Vec::new();
for iovec in iovecs.iter() {
slices.push(IoSlice::new(unsafe { std::mem::transmute(*iovec) }));
}
let result = {
// Take the semaphore to ensure other threads are not interacting
// with the underlying file.
let _lock = semaphore.lock().unwrap();
// Move the cursor to the right offset
file.seek(SeekFrom::Start(offset as u64))
.map_err(AsyncIoError::WriteVectored)?;
// Write vectored
file.write_vectored(slices.as_slice())
.map_err(AsyncIoError::WriteVectored)?
};
completion_list.push((user_data, result as i32));
eventfd.write(1).unwrap();
Ok(())
}
pub fn fsync_sync(
user_data: Option<u64>,
file: &mut dyn Write,
eventfd: &EventFd,
completion_list: &mut Vec<(u64, i32)>,
semaphore: &mut Arc<Mutex<()>>,
) -> AsyncIoResult<()> {
let result: i32 = {
// Take the semaphore to ensure other threads are not interacting
// with the underlying file.
let _lock = semaphore.lock().unwrap();
// Flush
file.flush().map_err(AsyncIoError::Fsync)?;
0
};
if let Some(user_data) = user_data {
completion_list.push((user_data, result));
eventfd.write(1).unwrap();
}
Ok(())
}
pub enum ImageType {
FixedVhd,
Qcow2,
Raw,
}
const QCOW_MAGIC: u32 = 0x5146_49fb;
/// Determine image type through file parsing.
pub fn detect_image_type(f: &mut File) -> std::io::Result<ImageType> {
// We must create a buffer aligned on 512 bytes with a size being a
// multiple of 512 bytes as the file might be opened with O_DIRECT flag.
#[repr(align(512))]
struct Sector {
data: [u8; 512],
}
let mut s = Sector { data: [0; 512] };
f.read_exact(&mut s.data)?;
// Check 4 first bytes to get the header value and determine the image type
let image_type = if u32::from_be_bytes(s.data[0..4].try_into().unwrap()) == QCOW_MAGIC {
ImageType::Qcow2
} else if vhd::is_fixed_vhd(f)? {
ImageType::FixedVhd
} else {
ImageType::Raw
};
Ok(image_type)
}

111
block_util/src/qcow_sync.rs Normal file
View File

@@ -0,0 +1,111 @@
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use crate::async_io::{AsyncIo, AsyncIoResult, DiskFile, DiskFileResult};
use crate::{disk_size, fsync_sync, read_vectored_sync, write_vectored_sync};
use qcow::{QcowFile, RawFile};
use std::fs::File;
use std::sync::{Arc, Mutex};
use vmm_sys_util::eventfd::EventFd;
pub struct QcowDiskSync {
qcow_file: QcowFile,
semaphore: Arc<Mutex<()>>,
}
impl QcowDiskSync {
pub fn new(file: File, direct_io: bool) -> Self {
QcowDiskSync {
qcow_file: QcowFile::from(RawFile::new(file, direct_io))
.expect("Failed creating QcowFile"),
semaphore: Arc::new(Mutex::new(())),
}
}
}
impl DiskFile for QcowDiskSync {
fn size(&mut self) -> DiskFileResult<u64> {
disk_size(&mut self.qcow_file, &mut self.semaphore)
}
fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
Ok(Box::new(QcowSync::new(
self.qcow_file.clone(),
self.semaphore.clone(),
)) as Box<dyn AsyncIo>)
}
}
pub struct QcowSync {
qcow_file: QcowFile,
eventfd: EventFd,
completion_list: Vec<(u64, i32)>,
semaphore: Arc<Mutex<()>>,
}
impl QcowSync {
pub fn new(qcow_file: QcowFile, semaphore: Arc<Mutex<()>>) -> Self {
QcowSync {
qcow_file,
eventfd: EventFd::new(libc::EFD_NONBLOCK)
.expect("Failed creating EventFd for QcowSync"),
completion_list: Vec::new(),
semaphore,
}
}
}
impl AsyncIo for QcowSync {
fn notifier(&self) -> &EventFd {
&self.eventfd
}
fn read_vectored(
&mut self,
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
) -> AsyncIoResult<()> {
read_vectored_sync(
offset,
iovecs,
user_data,
&mut self.qcow_file,
&self.eventfd,
&mut self.completion_list,
&mut self.semaphore,
)
}
fn write_vectored(
&mut self,
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
) -> AsyncIoResult<()> {
write_vectored_sync(
offset,
iovecs,
user_data,
&mut self.qcow_file,
&self.eventfd,
&mut self.completion_list,
&mut self.semaphore,
)
}
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> {
fsync_sync(
user_data,
&mut self.qcow_file,
&self.eventfd,
&mut self.completion_list,
&mut self.semaphore,
)
}
fn complete(&mut self) -> Vec<(u64, i32)> {
self.completion_list.drain(..).collect()
}
}

159
block_util/src/raw_async.rs Normal file
View File

@@ -0,0 +1,159 @@
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
};
use io_uring::{opcode, squeue, types, IoUring};
use std::fs::File;
use std::io::{Seek, SeekFrom};
use std::os::unix::io::{AsRawFd, RawFd};
use vmm_sys_util::eventfd::EventFd;
pub struct RawFileDisk {
file: File,
}
impl RawFileDisk {
pub fn new(file: File) -> Self {
RawFileDisk { file }
}
}
impl DiskFile for RawFileDisk {
fn size(&mut self) -> DiskFileResult<u64> {
Ok(self
.file
.seek(SeekFrom::End(0))
.map_err(DiskFileError::Size)? as u64)
}
fn new_async_io(&self, ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
Ok(Box::new(
RawFileAsync::new(self.file.as_raw_fd(), ring_depth)
.map_err(DiskFileError::NewAsyncIo)?,
) as Box<dyn AsyncIo>)
}
}
pub struct RawFileAsync {
fd: RawFd,
io_uring: IoUring,
eventfd: EventFd,
}
impl RawFileAsync {
pub fn new(fd: RawFd, ring_depth: u32) -> std::io::Result<Self> {
let io_uring = IoUring::new(ring_depth)?;
let eventfd = EventFd::new(libc::EFD_NONBLOCK)?;
// Register the io_uring eventfd that will notify when something in
// the completion queue is ready.
io_uring.submitter().register_eventfd(eventfd.as_raw_fd())?;
Ok(RawFileAsync {
fd,
io_uring,
eventfd,
})
}
}
impl AsyncIo for RawFileAsync {
fn notifier(&self) -> &EventFd {
&self.eventfd
}
fn read_vectored(
&mut self,
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
) -> AsyncIoResult<()> {
let (submitter, mut sq, _) = self.io_uring.split();
// Safe because we know the file descriptor is valid and we
// relied on vm-memory to provide the buffer address.
let _ = unsafe {
sq.push(
&opcode::Readv::new(types::Fd(self.fd), iovecs.as_ptr(), iovecs.len() as u32)
.offset(offset)
.build()
.flags(squeue::Flags::ASYNC)
.user_data(user_data),
)
};
// Update the submission queue and submit new operations to the
// io_uring instance.
sq.sync();
submitter.submit().map_err(AsyncIoError::ReadVectored)?;
Ok(())
}
fn write_vectored(
&mut self,
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
) -> AsyncIoResult<()> {
let (submitter, mut sq, _) = self.io_uring.split();
// Safe because we know the file descriptor is valid and we
// relied on vm-memory to provide the buffer address.
let _ = unsafe {
sq.push(
&opcode::Writev::new(types::Fd(self.fd), iovecs.as_ptr(), iovecs.len() as u32)
.offset(offset)
.build()
.flags(squeue::Flags::ASYNC)
.user_data(user_data),
)
};
// Update the submission queue and submit new operations to the
// io_uring instance.
sq.sync();
submitter.submit().map_err(AsyncIoError::WriteVectored)?;
Ok(())
}
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> {
if let Some(user_data) = user_data {
let (submitter, mut sq, _) = self.io_uring.split();
// Safe because we know the file descriptor is valid.
let _ = unsafe {
sq.push(
&opcode::Fsync::new(types::Fd(self.fd))
.build()
.flags(squeue::Flags::ASYNC)
.user_data(user_data),
)
};
// Update the submission queue and submit new operations to the
// io_uring instance.
sq.sync();
submitter.submit().map_err(AsyncIoError::Fsync)?;
} else {
unsafe { libc::fsync(self.fd) };
}
Ok(())
}
fn complete(&mut self) -> Vec<(u64, i32)> {
let mut completion_list = Vec::new();
let cq = self.io_uring.completion();
for cq_entry in cq {
completion_list.push((cq_entry.user_data(), cq_entry.result()));
}
completion_list
}
}

122
block_util/src/raw_sync.rs Normal file
View File

@@ -0,0 +1,122 @@
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
};
use std::fs::File;
use std::io::{Seek, SeekFrom};
use std::os::unix::io::{AsRawFd, RawFd};
use vmm_sys_util::eventfd::EventFd;
pub struct RawFileDiskSync {
file: File,
}
impl RawFileDiskSync {
pub fn new(file: File) -> Self {
RawFileDiskSync { file }
}
}
impl DiskFile for RawFileDiskSync {
fn size(&mut self) -> DiskFileResult<u64> {
Ok(self
.file
.seek(SeekFrom::End(0))
.map_err(DiskFileError::Size)? as u64)
}
fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
Ok(Box::new(RawFileSync::new(self.file.as_raw_fd())) as Box<dyn AsyncIo>)
}
}
pub struct RawFileSync {
fd: RawFd,
eventfd: EventFd,
completion_list: Vec<(u64, i32)>,
}
impl RawFileSync {
pub fn new(fd: RawFd) -> Self {
RawFileSync {
fd,
eventfd: EventFd::new(libc::EFD_NONBLOCK).expect("Failed creating EventFd for RawFile"),
completion_list: Vec::new(),
}
}
}
impl AsyncIo for RawFileSync {
fn notifier(&self) -> &EventFd {
&self.eventfd
}
fn read_vectored(
&mut self,
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
) -> AsyncIoResult<()> {
let result = unsafe {
libc::preadv(
self.fd as libc::c_int,
iovecs.as_ptr() as *const libc::iovec,
iovecs.len() as libc::c_int,
offset,
)
};
if result < 0 {
return Err(AsyncIoError::ReadVectored(std::io::Error::last_os_error()));
}
self.completion_list.push((user_data, result as i32));
self.eventfd.write(1).unwrap();
Ok(())
}
fn write_vectored(
&mut self,
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
) -> AsyncIoResult<()> {
let result = unsafe {
libc::pwritev(
self.fd as libc::c_int,
iovecs.as_ptr() as *const libc::iovec,
iovecs.len() as libc::c_int,
offset,
)
};
if result < 0 {
return Err(AsyncIoError::WriteVectored(std::io::Error::last_os_error()));
}
self.completion_list.push((user_data, result as i32));
self.eventfd.write(1).unwrap();
Ok(())
}
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> {
let result = unsafe { libc::fsync(self.fd as libc::c_int) };
if result < 0 {
return Err(AsyncIoError::Fsync(std::io::Error::last_os_error()));
}
if let Some(user_data) = user_data {
self.completion_list.push((user_data, result as i32));
self.eventfd.write(1).unwrap();
}
Ok(())
}
fn complete(&mut self) -> Vec<(u64, i32)> {
self.completion_list.drain(..).collect()
}
}

221
block_util/src/vhd.rs Normal file
View File

@@ -0,0 +1,221 @@
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
use std::convert::TryInto;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
#[derive(Clone, Copy)]
pub struct VhdFooter {
cookie: u64,
features: u32,
file_format_version: u32,
data_offset: u64,
time_stamp: u32,
creator_application: u32,
creator_version: u32,
creator_host_os: u32,
original_size: u64,
current_size: u64,
disk_geometry: u32,
disk_type: u32,
checksum: u32,
unique_id: u128,
saved_state: u8,
}
impl VhdFooter {
pub fn new(file: &mut File) -> std::io::Result<VhdFooter> {
// We must create a buffer aligned on 512 bytes with a size being a
// multiple of 512 bytes as the file might be opened with O_DIRECT flag.
#[repr(align(512))]
struct Sector {
data: [u8; 512],
}
let mut s = Sector { data: [0; 512] };
// Place the cursor 512 bytes before the end of the file, as this is
// where the footer starts.
file.seek(SeekFrom::End(-512))?;
// Fill in the VhdFooter structure
file.read_exact(&mut s.data)?;
Ok(VhdFooter {
cookie: u64::from_be_bytes(s.data[0..8].try_into().unwrap()),
features: u32::from_be_bytes(s.data[8..12].try_into().unwrap()),
file_format_version: u32::from_be_bytes(s.data[12..16].try_into().unwrap()),
data_offset: u64::from_be_bytes(s.data[16..24].try_into().unwrap()),
time_stamp: u32::from_be_bytes(s.data[24..28].try_into().unwrap()),
creator_application: u32::from_be_bytes(s.data[28..32].try_into().unwrap()),
creator_version: u32::from_be_bytes(s.data[32..36].try_into().unwrap()),
creator_host_os: u32::from_be_bytes(s.data[36..40].try_into().unwrap()),
original_size: u64::from_be_bytes(s.data[40..48].try_into().unwrap()),
current_size: u64::from_be_bytes(s.data[48..56].try_into().unwrap()),
disk_geometry: u32::from_be_bytes(s.data[56..60].try_into().unwrap()),
disk_type: u32::from_be_bytes(s.data[60..64].try_into().unwrap()),
checksum: u32::from_be_bytes(s.data[64..68].try_into().unwrap()),
unique_id: u128::from_be_bytes(s.data[68..84].try_into().unwrap()),
saved_state: u8::from_be_bytes(s.data[84..85].try_into().unwrap()),
})
}
pub fn cookie(&self) -> u64 {
self.cookie
}
pub fn features(&self) -> u32 {
self.features
}
pub fn file_format_version(&self) -> u32 {
self.file_format_version
}
pub fn data_offset(&self) -> u64 {
self.data_offset
}
pub fn time_stamp(&self) -> u32 {
self.time_stamp
}
pub fn creator_application(&self) -> u32 {
self.creator_application
}
pub fn creator_version(&self) -> u32 {
self.creator_version
}
pub fn creator_host_os(&self) -> u32 {
self.creator_host_os
}
pub fn original_size(&self) -> u64 {
self.original_size
}
pub fn current_size(&self) -> u64 {
self.current_size
}
pub fn disk_geometry(&self) -> u32 {
self.disk_geometry
}
pub fn disk_type(&self) -> u32 {
self.disk_type
}
pub fn checksum(&self) -> u32 {
self.checksum
}
pub fn unique_id(&self) -> u128 {
self.unique_id
}
pub fn saved_state(&self) -> u8 {
self.saved_state
}
}
/// Determine image type through file parsing.
pub fn is_fixed_vhd(f: &mut File) -> std::io::Result<bool> {
let footer = VhdFooter::new(f)?;
// "conectix" => 0x636f6e6563746978
Ok(footer.cookie() == 0x636f6e6563746978
&& footer.file_format_version() == 0x0001_0000
&& footer.data_offset() == 0xffff_ffff_ffff_ffff
&& footer.disk_type() == 0x2)
}
#[cfg(test)]
mod tests {
use super::{is_fixed_vhd, VhdFooter};
use std::fs::File;
use std::io::{Seek, SeekFrom, Write};
use vmm_sys_util::tempfile::TempFile;
fn valid_fixed_vhd_footer() -> Vec<u8> {
vec![
0x63, 0x6f, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x78, // cookie
0x00, 0x00, 0x00, 0x02, // features
0x00, 0x01, 0x00, 0x00, // file format version
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // data offset
0x27, 0xa6, 0xa6, 0x5d, // time stamp
0x71, 0x65, 0x6d, 0x75, // creator application
0x00, 0x05, 0x00, 0x03, // creator version
0x57, 0x69, 0x32, 0x6b, // creator host os
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // original size
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // current size
0x11, 0xe0, 0x10, 0x3f, // disk geometry
0x00, 0x00, 0x00, 0x02, // disk type
0x00, 0x00, 0x00, 0x00, // checksum
0x98, 0x7b, 0xb1, 0xcd, 0x84, 0x14, 0x41, 0xfc, 0xa4, 0xab, 0xd0, 0x69, 0x45, 0x2b,
0xf2, 0x23, // unique id
0x00, // saved state
]
}
fn valid_dynamic_vhd_footer() -> Vec<u8> {
vec![
0x63, 0x6f, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x78, // cookie
0x00, 0x00, 0x00, 0x02, // features
0x00, 0x01, 0x00, 0x00, // file format version
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // data offset
0x27, 0xa6, 0xa6, 0x5d, // time stamp
0x71, 0x65, 0x6d, 0x75, // creator application
0x00, 0x05, 0x00, 0x03, // creator version
0x57, 0x69, 0x32, 0x6b, // creator host os
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // original size
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // current size
0x11, 0xe0, 0x10, 0x3f, // disk geometry
0x00, 0x00, 0x00, 0x03, // disk type
0x00, 0x00, 0x00, 0x00, // checksum
0x98, 0x7b, 0xb1, 0xcd, 0x84, 0x14, 0x41, 0xfc, 0xa4, 0xab, 0xd0, 0x69, 0x45, 0x2b,
0xf2, 0x23, // unique id
0x00, // saved state
]
}
fn with_file<F>(footer: &[u8], mut testfn: F)
where
F: FnMut(File),
{
let mut disk_file: File = TempFile::new().unwrap().into_file();
disk_file.set_len(0x1000_0200).unwrap();
disk_file.seek(SeekFrom::Start(0x1000_0000)).unwrap();
disk_file.write_all(&footer).unwrap();
testfn(disk_file); // File closed when the function exits.
}
#[test]
fn test_check_vhd_footer() {
with_file(&valid_fixed_vhd_footer(), |mut file: File| {
let vhd_footer = VhdFooter::new(&mut file).expect("Failed to create VHD footer");
assert_eq!(vhd_footer.cookie(), 0x636f_6e65_6374_6978);
assert_eq!(vhd_footer.features(), 0x0000_0002);
assert_eq!(vhd_footer.file_format_version(), 0x0001_0000);
assert_eq!(vhd_footer.data_offset(), 0xffff_ffff_ffff_ffff);
assert_eq!(vhd_footer.time_stamp(), 0x27a6_a65d);
assert_eq!(vhd_footer.creator_application(), 0x7165_6d75);
assert_eq!(vhd_footer.creator_version(), 0x0005_0003);
assert_eq!(vhd_footer.creator_host_os(), 0x5769_326b);
assert_eq!(vhd_footer.original_size(), 0x0000_0000_1000_0000);
assert_eq!(vhd_footer.current_size(), 0x0000_0000_1000_0000);
assert_eq!(vhd_footer.disk_geometry(), 0x11e0_103f);
assert_eq!(vhd_footer.disk_type(), 0x0000_0002);
assert_eq!(vhd_footer.checksum(), 0x0000_0000);
assert_eq!(
vhd_footer.unique_id(),
0x987b_b1cd_8414_41fc_a4ab_d069_452b_f223
);
assert_eq!(vhd_footer.saved_state(), 0x00);
});
}
#[test]
fn test_is_fixed_vhd() {
with_file(&valid_fixed_vhd_footer(), |mut file: File| {
assert!(is_fixed_vhd(&mut file).unwrap());
});
}
#[test]
fn test_is_not_fixed_vhd() {
with_file(&valid_dynamic_vhd_footer(), |mut file: File| {
assert!(!(is_fixed_vhd(&mut file).unwrap()));
});
}
}

View File

@@ -3,20 +3,25 @@
// SPDX-License-Identifier: Apache-2.0
//
#[macro_use(crate_version)]
extern crate clap;
use std::process::Command;
fn main() {
let git_out = Command::new("git")
.args(&["describe", "--dirty"])
.output()
.expect("Expect to get git describe output");
let mut version = "v".to_owned() + crate_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) {
version = git_out_str;
}
}
}
// This println!() has a special behavior, as it will set the environment
// variable BUILT_VERSION, so that it can be reused from the binary.
// Particularly, this is used from src/main.rs to display the exact
// version.
println!(
"cargo:rustc-env=BUILT_VERSION={}",
String::from_utf8(git_out.stdout).unwrap()
);
println!("cargo:rustc-env=BUILT_VERSION={}", version);
}

View File

@@ -6,22 +6,19 @@ authors = ["The Chromium OS Authors"]
[dependencies]
anyhow = "1.0"
bitflags = ">=1.2.1"
byteorder = "1.3.4"
byteorder = "1.4.3"
epoll = ">=4.0.1"
libc = "0.2.71"
log = "0.4.8"
libc = "0.2.91"
log = "0.4.14"
serde = {version = ">=1.0.27", features = ["rc"] }
serde_derive = ">=1.0.27"
serde_json = ">=1.0.9"
vm-device = { path = "../vm-device" }
acpi_tables = { path = "../acpi_tables", optional = true }
vm-memory = "0.2.1"
vm-memory = "0.5.0"
vm-migration = { path = "../vm-migration" }
vmm-sys-util = ">=0.3.1"
[dev-dependencies]
tempfile = "3.1.0"
[features]
default = []
acpi = ["acpi_tables"]

View File

@@ -4,11 +4,15 @@
//
use acpi_tables::{aml, aml::Aml};
use std::sync::Arc;
use std::sync::{Arc, Barrier};
use std::time::Instant;
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
use vm_memory::GuestAddress;
use vmm_sys_util::eventfd::EventFd;
use BusDevice;
use HotPlugNotificationFlags;
use AcpiNotificationFlags;
pub const GED_DEVICE_ACPI_SIZE: usize = 0x1;
/// A device for handling ACPI shutdown and reboot
pub struct AcpiShutdownDevice {
@@ -35,7 +39,7 @@ impl BusDevice for AcpiShutdownDevice {
}
}
fn write(&mut self, _base: u64, _offset: u64, data: &[u8]) {
fn write(&mut self, _base: u64, _offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
if data[0] == 1 {
debug!("ACPI Reboot signalled");
if let Err(e) = self.reset_evt.write(1) {
@@ -53,28 +57,35 @@ impl BusDevice for AcpiShutdownDevice {
error!("Error triggering ACPI shutdown event: {}", e);
}
}
None
}
}
/// A device for handling ACPI GED event generation
pub struct AcpiGEDDevice {
pub struct AcpiGedDevice {
interrupt: Arc<Box<dyn InterruptSourceGroup>>,
notification_type: HotPlugNotificationFlags,
notification_type: AcpiNotificationFlags,
ged_irq: u32,
address: GuestAddress,
}
impl AcpiGEDDevice {
pub fn new(interrupt: Arc<Box<dyn InterruptSourceGroup>>, ged_irq: u32) -> AcpiGEDDevice {
AcpiGEDDevice {
impl AcpiGedDevice {
pub fn new(
interrupt: Arc<Box<dyn InterruptSourceGroup>>,
ged_irq: u32,
address: GuestAddress,
) -> AcpiGedDevice {
AcpiGedDevice {
interrupt,
notification_type: HotPlugNotificationFlags::NO_DEVICES_CHANGED,
notification_type: AcpiNotificationFlags::NO_DEVICES_CHANGED,
ged_irq,
address,
}
}
pub fn notify(
&mut self,
notification_type: HotPlugNotificationFlags,
notification_type: AcpiNotificationFlags,
) -> Result<(), std::io::Error> {
self.notification_type |= notification_type;
self.interrupt.trigger(0)
@@ -86,18 +97,16 @@ impl AcpiGEDDevice {
}
// I/O port reports what type of notification was made
impl BusDevice for AcpiGEDDevice {
impl BusDevice for AcpiGedDevice {
// Spec has all fields as zero
fn read(&mut self, _base: u64, _offset: u64, data: &mut [u8]) {
data[0] = self.notification_type.bits();
self.notification_type = HotPlugNotificationFlags::NO_DEVICES_CHANGED;
self.notification_type = AcpiNotificationFlags::NO_DEVICES_CHANGED;
}
fn write(&mut self, _base: u64, _offset: u64, _data: &[u8]) {}
}
#[cfg(feature = "acpi")]
impl Aml for AcpiGEDDevice {
impl Aml for AcpiGedDevice {
fn to_aml_bytes(&self) -> Vec<u8> {
aml::Device::new(
"_SB_.GED_".into(),
@@ -114,7 +123,12 @@ impl Aml for AcpiGEDDevice {
self.ged_irq,
)]),
),
&aml::OpRegion::new("GDST".into(), aml::OpRegionSpace::SystemIO, 0xb000, 0x1),
&aml::OpRegion::new(
"GDST".into(),
aml::OpRegionSpace::SystemMemory,
self.address.0 as usize,
GED_DEVICE_ACPI_SIZE,
),
&aml::Field::new(
"GDST".into(),
aml::FieldAccessType::Byte,
@@ -142,6 +156,14 @@ impl Aml for AcpiGEDDevice {
&aml::Equal::new(&aml::Local(1), &4usize),
vec![&aml::MethodCall::new("\\_SB_.PCI0.PCNT".into(), vec![])],
),
&aml::And::new(&aml::Local(1), &aml::Local(0), &8usize),
&aml::If::new(
&aml::Equal::new(&aml::Local(1), &8usize),
vec![&aml::Notify::new(
&aml::Path::new("\\_SB_.PWRB"),
&0x80usize,
)],
),
],
),
],
@@ -149,3 +171,37 @@ impl Aml for AcpiGEDDevice {
.to_aml_bytes()
}
}
pub struct AcpiPmTimerDevice {
start: Instant,
}
impl AcpiPmTimerDevice {
pub fn new() -> Self {
Self {
start: Instant::now(),
}
}
}
impl Default for AcpiPmTimerDevice {
fn default() -> Self {
Self::new()
}
}
impl BusDevice for AcpiPmTimerDevice {
fn read(&mut self, _base: u64, _offset: u64, data: &mut [u8]) {
let now = Instant::now();
let since = now.duration_since(self.start);
let nanos = since.as_nanos();
const PM_TIMER_FREQUENCY_HZ: u128 = 3_579_545;
const NANOS_PER_SECOND: u128 = 1_000_000_000;
let counter = (nanos * PM_TIMER_FREQUENCY_HZ) / NANOS_PER_SECOND;
let counter: u32 = (counter & 0xffff_ffff) as u32;
data.copy_from_slice(&counter.to_le_bytes());
}
}

View File

@@ -6,16 +6,16 @@ use super::interrupt_controller::{Error, InterruptController};
use std::result;
use std::sync::Arc;
use vm_device::interrupt::{
InterruptIndex, InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig,
InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup,
LegacyIrqSourceConfig, MsiIrqGroupConfig,
};
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vmm_sys_util::eventfd::EventFd;
type Result<T> = result::Result<T, Error>;
// Reserve 32 IRQs (GSI 32 ~ 64) for legacy device.
// GsiAllocator should allocate beyond this: from 64 on
// Reserve 32 IRQs for legacy device.
pub const IRQ_LEGACY_BASE: usize = 0;
pub const IRQ_LEGACY_COUNT: usize = 32;
pub const IRQ_SPI_OFFSET: usize = 32;
// This Gic struct implements InterruptController to provide interrupt delivery service.
// The Gic source files in arch/ folder maintain the Aarch64 specific Gic device.
@@ -34,7 +34,7 @@ impl Gic {
) -> Result<Gic> {
let interrupt_source_group = interrupt_manager
.create_group(MsiIrqGroupConfig {
base: IRQ_SPI_OFFSET as InterruptIndex,
base: IRQ_LEGACY_BASE as InterruptIndex,
count: IRQ_LEGACY_COUNT as InterruptIndex,
})
.map_err(Error::CreateInterruptSourceGroup)?;
@@ -47,10 +47,26 @@ impl Gic {
impl InterruptController for Gic {
fn enable(&self) -> Result<()> {
&self
.interrupt_source_group
// Set irqfd for legacy interrupts
self.interrupt_source_group
.enable()
.map_err(Error::EnableInterrupt)?;
// Set irq_routing for legacy interrupts.
// irqchip: Hardcode to 0 as we support only 1 GIC
// pin: Use irq number as pin
for i in IRQ_LEGACY_BASE..(IRQ_LEGACY_BASE + IRQ_LEGACY_COUNT) {
let config = LegacyIrqSourceConfig {
irqchip: 0,
pin: i as u32,
};
self.interrupt_source_group
.update(
i as InterruptIndex,
InterruptSourceConfig::LegacyIrq(config),
)
.map_err(Error::EnableInterrupt)?;
}
Ok(())
}
@@ -63,23 +79,8 @@ impl InterruptController for Gic {
Ok(())
}
}
const GIC_SNAPSHOT_ID: &str = "gic";
impl Snapshottable for Gic {
fn id(&self) -> String {
GIC_SNAPSHOT_ID.to_string()
}
fn snapshot(&self) -> std::result::Result<Snapshot, MigratableError> {
unimplemented!();
}
fn restore(&mut self, _snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
unimplemented!();
fn notifier(&self, irq: usize) -> Option<EventFd> {
self.interrupt_source_group.notifier(irq as InterruptIndex)
}
}
impl Pausable for Gic {}
impl Transportable for Gic {}
impl Migratable for Gic {}

View File

@@ -4,11 +4,10 @@
use std::io;
use std::result;
use vmm_sys_util::eventfd::EventFd;
#[derive(Debug)]
pub enum Error {
/// Invalid destination mode.
InvalidDestinationMode,
/// Invalid trigger mode.
InvalidTriggerMode,
/// Invalid delivery mode.
@@ -58,4 +57,5 @@ pub trait InterruptController: Send {
fn enable(&self) -> Result<()>;
#[cfg(target_arch = "x86_64")]
fn end_of_interrupt(&mut self, vec: u8);
fn notifier(&self, irq: usize) -> Option<EventFd>;
}

View File

@@ -10,20 +10,21 @@
// See https://pdos.csail.mit.edu/6.828/2016/readings/ia32/ioapic.pdf for a specification.
use super::interrupt_controller::{Error, InterruptController};
use crate::BusDevice;
use anyhow::anyhow;
use byteorder::{ByteOrder, LittleEndian};
use std::result;
use std::sync::Arc;
use std::sync::{Arc, Barrier};
use vm_device::interrupt::{
InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup,
MsiIrqGroupConfig, MsiIrqSourceConfig,
};
use vm_device::BusDevice;
use vm_memory::GuestAddress;
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, SnapshotDataSection, Snapshottable,
Transportable,
};
use vmm_sys_util::eventfd::EventFd;
#[derive(Serialize, Deserialize)]
#[serde(remote = "GuestAddress")]
@@ -67,10 +68,12 @@ fn trigger_mode(entry: RedirectionTableEntry) -> u8 {
fn interrupt_mask(entry: RedirectionTableEntry) -> u8 {
((entry >> 16) & 0x1u64) as u8
}
fn destination_field_physical(entry: RedirectionTableEntry) -> u8 {
((entry >> 56) & 0xfu64) as u8
}
fn destination_field_logical(entry: RedirectionTableEntry) -> u8 {
fn destination_field(entry: RedirectionTableEntry) -> u8 {
// When the destination mode is physical, the destination field should only
// be defined through bits 56-59, as defined in the IOAPIC specification.
// But from the APIC specification, the APIC ID is always defined on 8 bits
// no matter which destination mode is selected. That's why we always
// retrieve the destination field based on bits 56-63.
((entry >> 56) & 0xffu64) as u8
}
fn set_delivery_status(entry: &mut RedirectionTableEntry, val: u8) {
@@ -100,12 +103,6 @@ const IOWIN_OFF: u8 = 0x10;
const IOWIN_SCALE: u8 = 0x2;
const REG_MAX_OFFSET: u8 = IOWIN_OFF + (NUM_IOAPIC_PINS as u8 * 2) - 1;
#[repr(u8)]
enum DestinationMode {
Physical = 0,
Logical = 1,
}
#[repr(u8)]
enum TriggerMode {
Edge = 0,
@@ -116,9 +113,9 @@ enum TriggerMode {
enum DeliveryMode {
Fixed = 0b000,
Lowest = 0b001,
SMI = 0b010, // System management interrupt
Smi = 0b010, // System management interrupt
RemoteRead = 0b011, // This is no longer supported by intel.
NMI = 0b100, // Non maskable interrupt
Nmi = 0b100, // Non maskable interrupt
Init = 0b101,
Startup = 0b110,
External = 0b111,
@@ -171,7 +168,7 @@ impl BusDevice for Ioapic {
LittleEndian::write_u32(data, value);
}
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) {
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
assert!(data.len() == 4);
debug!("IOAPIC_W @ offset 0x{:x}", offset);
@@ -185,6 +182,7 @@ impl BusDevice for Ioapic {
error!("IOAPIC: failed writing at offset {}", offset);
}
}
None
}
}
@@ -196,20 +194,18 @@ impl Ioapic {
) -> Result<Ioapic> {
let interrupt_source_group = interrupt_manager
.create_group(MsiIrqGroupConfig {
base: 0 as InterruptIndex,
base: 0,
count: NUM_IOAPIC_PINS as InterruptIndex,
})
.map_err(Error::CreateInterruptSourceGroup)?;
interrupt_source_group
.enable()
.map_err(Error::EnableInterrupt)?;
// The IOAPIC is created with entries already masked. The guest will be
// in charge of unmasking them if/when necessary.
Ok(Ioapic {
id,
id_reg: 0,
reg_sel: 0,
reg_entries: [0; NUM_IOAPIC_PINS],
reg_entries: [0x10000; NUM_IOAPIC_PINS],
used_entries: [false; NUM_IOAPIC_PINS],
apic_address,
interrupt_source_group,
@@ -220,6 +216,16 @@ impl Ioapic {
debug!("IOAPIC_W reg 0x{:x}, val 0x{:x}", self.reg_sel, val);
match self.reg_sel as u8 {
IOAPIC_REG_VERSION => {
if val == 0 {
// Windows writes zero here (see #1791)
} else {
error!(
"IOAPIC: invalid write to version register (0x{:x}): 0x{:x}",
self.reg_sel, val
);
}
}
IOAPIC_REG_ID => self.id_reg = (val >> 24) & 0xf,
IOWIN_OFF..=REG_MAX_OFFSET => {
let (index, is_high_bits) = decode_irq_from_selector(self.reg_sel as u8);
@@ -241,7 +247,10 @@ impl Ioapic {
// Store the information this IRQ is now being used.
self.used_entries[index] = true;
}
_ => error!("IOAPIC: invalid write to register offset"),
_ => error!(
"IOAPIC: invalid write to register offset 0x{:x}",
self.reg_sel
),
}
}
@@ -260,7 +269,10 @@ impl Ioapic {
}
}
_ => {
error!("IOAPIC: invalid read from register offset");
error!(
"IOAPIC: invalid read from register offset 0x{:x}",
self.reg_sel
);
0
}
}
@@ -296,11 +308,7 @@ impl Ioapic {
// Validate Destination Mode value, and retrieve Destination ID
let destination_mode = destination_mode(entry);
let destination_id: u8 = match destination_mode {
x if x == DestinationMode::Physical as u8 => destination_field_physical(entry),
x if x == DestinationMode::Logical as u8 => destination_field_logical(entry),
_ => return Err(Error::InvalidDestinationMode),
};
let destination_id = destination_field(entry);
// When this bit is set, the message is directed to the processor with
// the lowest interrupt priority among processors that can receive the
@@ -325,9 +333,9 @@ impl Ioapic {
match delivery_mode {
x if (x == DeliveryMode::Fixed as u8)
|| (x == DeliveryMode::Lowest as u8)
|| (x == DeliveryMode::SMI as u8)
|| (x == DeliveryMode::Smi as u8)
|| (x == DeliveryMode::RemoteRead as u8)
|| (x == DeliveryMode::NMI as u8)
|| (x == DeliveryMode::Nmi as u8)
|| (x == DeliveryMode::Init as u8)
|| (x == DeliveryMode::Startup as u8)
|| (x == DeliveryMode::External as u8) => {}
@@ -344,6 +352,7 @@ impl Ioapic {
high_addr: 0x0,
low_addr,
data,
devid: 0,
};
self.interrupt_source_group
@@ -397,6 +406,10 @@ impl InterruptController for Ioapic {
Ok(())
}
fn notifier(&self, irq: usize) -> Option<EventFd> {
self.interrupt_source_group.notifier(irq as InterruptIndex)
}
}
impl Snapshottable for Ioapic {
@@ -404,7 +417,7 @@ impl Snapshottable for Ioapic {
self.id.clone()
}
fn snapshot(&self) -> std::result::Result<Snapshot, MigratableError> {
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
let snapshot =
serde_json::to_vec(&self.state()).map_err(|e| MigratableError::Snapshot(e.into()))?;

View File

@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use libc::{gmtime_r, time, time_t, tm};
use libc::{clock_gettime, gmtime_r, time_t, timespec, tm, CLOCK_REALTIME};
use std::cmp::min;
use std::mem;
use crate::BusDevice;
use std::sync::{Arc, Barrier};
use vm_device::BusDevice;
const INDEX_MASK: u8 = 0x7f;
const INDEX_OFFSET: u64 = 0x0;
@@ -45,16 +45,17 @@ impl Cmos {
}
impl BusDevice for Cmos {
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) {
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
if data.len() != 1 {
return;
return None;
}
match offset {
INDEX_OFFSET => self.index = data[0] & INDEX_MASK,
DATA_OFFSET => self.data[self.index as usize] = data[0],
o => panic!("bad write offset on CMOS device: {}", o),
}
};
None
}
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
@@ -77,14 +78,17 @@ impl BusDevice for Cmos {
let day;
let month;
let year;
// The time and gmtime_r calls are safe as long as the structs they are given are
// large enough, and neither of them fail. It is safe to zero initialize the tm
// struct because it contains only plain data.
unsafe {
// The clock_gettime and gmtime_r calls are safe as long as the structs they are
// given are large enough, and neither of them fail. It is safe to zero initialize
// the tm and timespec struct because it contains only plain data.
let update_in_progress = unsafe {
let mut timespec: timespec = mem::zeroed();
clock_gettime(CLOCK_REALTIME, &mut timespec as *mut _);
let now: time_t = timespec.tv_sec;
let mut tm: tm = mem::zeroed();
let mut now: time_t = 0;
time(&mut now as *mut _);
gmtime_r(&now, &mut tm as *mut _);
// The following lines of code are safe but depend on tm being in scope.
seconds = tm.tm_sec;
minutes = tm.tm_min;
@@ -93,6 +97,11 @@ impl BusDevice for Cmos {
day = tm.tm_mday;
month = tm.tm_mon + 1;
year = tm.tm_year;
// Update in Progress bit held for last 224us of each second
const NANOSECONDS_PER_SECOND: i64 = 1_000_000_000;
const UIP_HOLD_LENGTH: i64 = 8 * NANOSECONDS_PER_SECOND / 32768;
timespec.tv_nsec >= (NANOSECONDS_PER_SECOND - UIP_HOLD_LENGTH)
};
match self.index {
0x00 => to_bcd(seconds as u8),
@@ -102,6 +111,8 @@ impl BusDevice for Cmos {
0x07 => to_bcd(day as u8),
0x08 => to_bcd(month as u8),
0x09 => to_bcd((year % 100) as u8),
// Bit 5 for 32kHz clock. Bit 7 for Update in Progress
0x0a => 1 << 5 | (update_in_progress as u8) << 7,
0x32 => to_bcd(((year + 1900) / 100) as u8),
_ => {
// self.index is always guaranteed to be in range via INDEX_MASK.

View File

@@ -7,7 +7,8 @@
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
//
use BusDevice;
use std::sync::{Arc, Barrier};
use vm_device::BusDevice;
/// Provides firmware debug output via I/O port controls
#[derive(Default)]
@@ -30,11 +31,13 @@ impl BusDevice for FwDebugDevice {
}
}
fn write(&mut self, _base: u64, _offset: u64, data: &[u8]) {
fn write(&mut self, _base: u64, _offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
if data.len() == 1 {
print!("{}", data[0] as char);
} else {
error!("Invalid write size on debug port: {}", data.len())
}
None
}
}

View File

@@ -0,0 +1,484 @@
// Copyright 2021 Arm Limited (or its affiliates). All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0
//! ARM PrimeCell General Purpose Input/Output(PL061)
//!
//! This module implements an ARM PrimeCell General Purpose Input/Output(PL061) to support gracefully poweroff microvm from external.
//!
use crate::{read_le_u32, write_le_u32};
use anyhow::anyhow;
use std::result;
use std::sync::{Arc, Barrier};
use std::{fmt, io};
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, SnapshotDataSection, Snapshottable,
Transportable,
};
const OFS_DATA: u64 = 0x400; // Data Register
const GPIODIR: u64 = 0x400; // Direction Register
const GPIOIS: u64 = 0x404; // Interrupt Sense Register
const GPIOIBE: u64 = 0x408; // Interrupt Both Edges Register
const GPIOIEV: u64 = 0x40c; // Interrupt Event Register
const GPIOIE: u64 = 0x410; // Interrupt Mask Register
const GPIORIE: u64 = 0x414; // Raw Interrupt Status Register
const GPIOMIS: u64 = 0x418; // Masked Interrupt Status Register
const GPIOIC: u64 = 0x41c; // Interrupt Clear Register
const GPIOAFSEL: u64 = 0x420; // Mode Control Select Register
// From 0x424 to 0xFDC => reserved space.
// From 0xFE0 to 0xFFC => Peripheral and PrimeCell Identification Registers which are Read Only registers.
// Thses registers can conceptually be treated as a 32-bit register, and PartNumber[11:0] is used to identify the peripheral.
// We are putting the expected values (look at 'Reset value' column from above mentioned document) in an array.
const GPIO_ID: [u8; 8] = [0x61, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
// ID Margins
const GPIO_ID_LOW: u64 = 0xfe0;
const GPIO_ID_HIGH: u64 = 0x1000;
const N_GPIOS: u32 = 8;
#[derive(Debug)]
pub enum Error {
BadWriteOffset(u64),
GpioInterruptDisabled,
GpioInterruptFailure(io::Error),
GpioTriggerKeyFailure(u32),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::BadWriteOffset(offset) => write!(f, "Bad Write Offset: {}", offset),
Error::GpioInterruptDisabled => write!(f, "GPIO interrupt disabled by guest driver.",),
Error::GpioInterruptFailure(ref e) => {
write!(f, "Could not trigger GPIO interrupt: {}.", e)
}
Error::GpioTriggerKeyFailure(key) => {
write!(f, "Invalid GPIO Input key triggerd: {}.", key)
}
}
}
}
type Result<T> = result::Result<T, Error>;
/// A GPIO device following the PL061 specification.
pub struct Gpio {
id: String,
// Data Register
data: u32,
old_in_data: u32,
// Direction Register
dir: u32,
// Interrupt Sense Register
isense: u32,
// Interrupt Both Edges Register
ibe: u32,
// Interrupt Event Register
iev: u32,
// Interrupt Mask Register
im: u32,
// Raw Interrupt Status Register
istate: u32,
// Mode Control Select Register
afsel: u32,
// GPIO irq_field
interrupt: Arc<Box<dyn InterruptSourceGroup>>,
}
#[derive(Serialize, Deserialize)]
pub struct GpioState {
data: u32,
old_in_data: u32,
dir: u32,
isense: u32,
ibe: u32,
iev: u32,
im: u32,
istate: u32,
afsel: u32,
}
impl Gpio {
/// Constructs an PL061 GPIO device.
pub fn new(id: String, interrupt: Arc<Box<dyn InterruptSourceGroup>>) -> Self {
Self {
id,
data: 0,
old_in_data: 0,
dir: 0,
isense: 0,
ibe: 0,
iev: 0,
im: 0,
istate: 0,
afsel: 0,
interrupt,
}
}
fn state(&self) -> GpioState {
GpioState {
data: self.data,
old_in_data: self.old_in_data,
dir: self.dir,
isense: self.isense,
ibe: self.ibe,
iev: self.iev,
im: self.im,
istate: self.istate,
afsel: self.afsel,
}
}
fn set_state(&mut self, state: &GpioState) {
self.data = state.data;
self.old_in_data = state.old_in_data;
self.dir = state.dir;
self.isense = state.isense;
self.ibe = state.ibe;
self.iev = state.iev;
self.im = state.im;
self.istate = state.istate;
self.afsel = state.afsel;
}
fn pl061_internal_update(&mut self) {
// FIXME:
// Missing Output Interrupt Emulation.
// Input Edging Interrupt Emulation.
let changed = ((self.old_in_data ^ self.data) & !self.dir) as u32;
if changed > 0 {
self.old_in_data = self.data;
for i in 0..N_GPIOS {
let mask = (1 << i) as u32;
if (changed & mask) > 0 {
// Bits set high in GPIOIS(Interrupt sense register) configure the corresponding
// pins to detect levels, otherwise, detect edges.
if (self.isense & mask) == 0 {
if (self.ibe & mask) > 0 {
// Bits set high in GPIOIBE(Interrupt both-edges register) configure the corresponding
// pins to detect both falling and rising edges.
// Clearing a bit configures the pin to be controlled by GPIOIEV.
self.istate |= mask;
} else {
// Bits set to high in GPIOIEV(Interrupt event register) configure the
// corresponding pin to detect rising edges, otherwise, detect falling edges.
self.istate |= !(self.data ^ self.iev) & mask;
}
}
}
}
}
// Input Level Interrupt Emulation.
self.istate |= !(self.data ^ self.iev) & self.isense;
}
fn handle_write(&mut self, offset: u64, val: u32) -> Result<()> {
if offset < OFS_DATA {
// In order to write to data register, the corresponding bits in the mask, resulting
// from the offsite[9:2], must be HIGH. otherwise the bit values remain unchanged.
let mask = (offset >> 2) as u32 & self.dir;
self.data = (self.data & !mask) | (val & mask);
} else {
match offset {
GPIODIR => {
/* Direction Register */
self.dir = val & 0xff;
}
GPIOIS => {
/* Interrupt Sense Register */
self.isense = val & 0xff;
}
GPIOIBE => {
/* Interrupt Both Edges Register */
self.ibe = val & 0xff;
}
GPIOIEV => {
/* Interrupt Event Register */
self.iev = val & 0xff;
}
GPIOIE => {
/* Interrupt Mask Register */
self.im = val & 0xff;
}
GPIOIC => {
/* Interrupt Clear Register */
self.istate &= !val;
}
GPIOAFSEL => {
/* Mode Control Select Register */
self.afsel = val & 0xff;
}
o => {
return Err(Error::BadWriteOffset(o));
}
}
}
Ok(())
}
pub fn trigger_key(&mut self, key: u32) -> Result<()> {
let mask = (1 << key) as u32;
if (!self.dir & mask) > 0 {
// emulate key event
// By default, Input Pin is configured to detect both rising and falling edges.
// So reverse the input pin data to generate a pulse.
self.data |= !(self.data & mask) & mask;
self.pl061_internal_update();
match self.trigger_gpio_interrupt() {
Ok(_) | Err(Error::GpioInterruptDisabled) => return Ok(()),
Err(e) => return Err(e),
}
}
Err(Error::GpioTriggerKeyFailure(key))
}
fn trigger_gpio_interrupt(&self) -> Result<()> {
// Bits set to high in GPIOIE(Interrupt mask register) allow the corresponding pins to
// trigger their individual interrupts and then the combined GPIOINTR line.
if (self.istate & self.im) == 0 {
warn!("Failed to trigger GPIO input interrupt (disabled by guest OS)");
return Err(Error::GpioInterruptDisabled);
}
self.interrupt
.trigger(0)
.map_err(Error::GpioInterruptFailure)?;
Ok(())
}
}
impl BusDevice for Gpio {
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
let value;
let mut read_ok = true;
if (GPIO_ID_LOW..GPIO_ID_HIGH).contains(&offset) {
let index = ((offset - GPIO_ID_LOW) >> 2) as usize;
value = u32::from(GPIO_ID[index]);
} else if offset < OFS_DATA {
value = self.data & ((offset >> 2) as u32)
} else {
value = match offset {
GPIODIR => self.dir,
GPIOIS => self.isense,
GPIOIBE => self.ibe,
GPIOIEV => self.iev,
GPIOIE => self.im,
GPIORIE => self.istate,
GPIOMIS => self.istate & self.im,
GPIOAFSEL => self.afsel,
_ => {
read_ok = false;
0
}
};
}
if read_ok && data.len() <= 4 {
write_le_u32(data, value);
} else {
warn!(
"Invalid GPIO PL061 read: offset {}, data length {}",
offset,
data.len()
);
}
}
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
if data.len() <= 4 {
let value = read_le_u32(&data);
if let Err(e) = self.handle_write(offset, value) {
warn!("Failed to write to GPIO PL061 device: {}", e);
}
} else {
warn!(
"Invalid GPIO PL061 write: offset {}, data length {}",
offset,
data.len()
);
}
None
}
}
impl Snapshottable for Gpio {
fn id(&self) -> String {
self.id.clone()
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
let snapshot =
serde_json::to_vec(&self.state()).map_err(|e| MigratableError::Snapshot(e.into()))?;
let mut gpio_snapshot = Snapshot::new(self.id.as_str());
gpio_snapshot.add_data_section(SnapshotDataSection {
id: format!("{}-section", self.id),
snapshot,
});
Ok(gpio_snapshot)
}
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
if let Some(gpio_section) = snapshot.snapshot_data.get(&format!("{}-section", self.id)) {
let gpio_state = match serde_json::from_slice(&gpio_section.snapshot) {
Ok(state) => state,
Err(error) => {
return Err(MigratableError::Restore(anyhow!(
"Could not deserialize GPIO {}",
error
)))
}
};
self.set_state(&gpio_state);
return Ok(());
}
Err(MigratableError::Restore(anyhow!(
"Could not find the GPIO snapshot section"
)))
}
}
impl Pausable for Gpio {}
impl Transportable for Gpio {}
impl Migratable for Gpio {}
#[cfg(test)]
mod tests {
use super::*;
use crate::{read_le_u32, write_le_u32};
use std::sync::Arc;
use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig};
use vmm_sys_util::eventfd::EventFd;
const GPIO_NAME: &str = "gpio";
const LEGACY_GPIO_MAPPED_IO_START: u64 = 0x0902_0000;
struct TestInterrupt {
event_fd: EventFd,
}
impl InterruptSourceGroup for TestInterrupt {
fn trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error> {
self.event_fd.write(1)
}
fn update(
&self,
_index: InterruptIndex,
_config: InterruptSourceConfig,
) -> result::Result<(), std::io::Error> {
Ok(())
}
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
Some(self.event_fd.try_clone().unwrap())
}
}
impl TestInterrupt {
fn new(event_fd: EventFd) -> Self {
TestInterrupt { event_fd }
}
}
#[test]
fn test_gpio_read_write_and_event() {
let intr_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap();
let mut gpio = Gpio::new(
String::from(GPIO_NAME),
Arc::new(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap()))),
);
let mut data = [0; 4];
// Read and write to the GPIODIR register.
// Set pin 0 output pin.
write_le_u32(&mut data, 1);
gpio.write(LEGACY_GPIO_MAPPED_IO_START, GPIODIR, &mut data);
gpio.read(LEGACY_GPIO_MAPPED_IO_START, GPIODIR, &mut data);
let v = read_le_u32(&data);
assert_eq!(v, 1);
// Read and write to the GPIODATA register.
write_le_u32(&mut data, 1);
// Set pin 0 high.
let offset = 0x00000004 as u64;
gpio.write(LEGACY_GPIO_MAPPED_IO_START, offset, &mut data);
gpio.read(LEGACY_GPIO_MAPPED_IO_START, offset, &mut data);
let v = read_le_u32(&data);
assert_eq!(v, 1);
// Read and write to the GPIOIS register.
// Configure pin 0 detecting level interrupt.
write_le_u32(&mut data, 1);
gpio.write(LEGACY_GPIO_MAPPED_IO_START, GPIOIS, &mut data);
gpio.read(LEGACY_GPIO_MAPPED_IO_START, GPIOIS, &mut data);
let v = read_le_u32(&data);
assert_eq!(v, 1);
// Read and write to the GPIOIBE register.
// Configure pin 1 detecting both falling and rising edges.
write_le_u32(&mut data, 2);
gpio.write(LEGACY_GPIO_MAPPED_IO_START, GPIOIBE, &mut data);
gpio.read(LEGACY_GPIO_MAPPED_IO_START, GPIOIBE, &mut data);
let v = read_le_u32(&data);
assert_eq!(v, 2);
// Read and write to the GPIOIEV register.
// Configure pin 2 detecting both falling and rising edges.
write_le_u32(&mut data, 4);
gpio.write(LEGACY_GPIO_MAPPED_IO_START, GPIOIEV, &mut data);
gpio.read(LEGACY_GPIO_MAPPED_IO_START, GPIOIEV, &mut data);
let v = read_le_u32(&data);
assert_eq!(v, 4);
// Read and write to the GPIOIE register.
// Configure pin 0...2 capable of triggering their individual interrupts
// and then the combined GPIOINTR line.
write_le_u32(&mut data, 7);
gpio.write(LEGACY_GPIO_MAPPED_IO_START, GPIOIE, &mut data);
gpio.read(LEGACY_GPIO_MAPPED_IO_START, GPIOIE, &mut data);
let v = read_le_u32(&data);
assert_eq!(v, 7);
let mask = 0x00000002 as u32;
// emulate an rising pulse in pin 1.
gpio.data |= !(gpio.data & mask) & mask;
gpio.pl061_internal_update();
// The interrupt line on pin 1 should be on.
// Read the GPIOMIS register.
gpio.read(LEGACY_GPIO_MAPPED_IO_START, GPIOMIS, &mut data);
let v = read_le_u32(&data);
assert_eq!(v, 2);
// Read and Write to the GPIOIC register.
// clear interrupt in pin 1.
write_le_u32(&mut data, 2);
gpio.write(LEGACY_GPIO_MAPPED_IO_START, GPIOIC, &mut data);
gpio.read(LEGACY_GPIO_MAPPED_IO_START, GPIOIC, &mut data);
let v = read_le_u32(&data);
assert_eq!(v, 2);
// Attempts to write beyond the writable space.
write_le_u32(&mut data, 0);
gpio.write(LEGACY_GPIO_MAPPED_IO_START, GPIO_ID_LOW, &mut data);
let mut data = [0; 4];
gpio.read(LEGACY_GPIO_MAPPED_IO_START, GPIO_ID_LOW, &mut data);
let index = GPIO_ID_LOW + 3;
assert_eq!(data[0], GPIO_ID[((index - GPIO_ID_LOW) >> 2) as usize]);
}
}

View File

@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
use std::sync::{Arc, Barrier};
use vm_device::BusDevice;
use vmm_sys_util::eventfd::EventFd;
use BusDevice;
/// A i8042 PS/2 controller that emulates just enough to shutdown the machine.
pub struct I8042Device {
reset_evt: EventFd,
@@ -32,12 +32,14 @@ impl BusDevice for I8042Device {
}
}
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) {
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
if data.len() == 1 && data[0] == 0xfe && offset == 3 {
debug!("i8042 reset signalled");
if let Err(e) = self.reset_evt.write(1) {
error!("Error triggering i8042 reset event: {}", e);
}
}
None
}
}

View File

@@ -9,10 +9,14 @@
mod cmos;
#[cfg(feature = "fwdebug")]
mod fwdebug;
#[cfg(target_arch = "aarch64")]
mod gpio_pl061;
mod i8042;
#[cfg(target_arch = "aarch64")]
mod rtc_pl031;
mod serial;
#[cfg(target_arch = "aarch64")]
mod uart_pl011;
#[cfg(feature = "cmos")]
pub use self::cmos::Cmos;
@@ -22,4 +26,10 @@ pub use self::i8042::I8042Device;
pub use self::serial::Serial;
#[cfg(target_arch = "aarch64")]
pub use self::rtc_pl031::RTC;
pub use self::gpio_pl061::Error as GpioDeviceError;
#[cfg(target_arch = "aarch64")]
pub use self::gpio_pl061::Gpio;
#[cfg(target_arch = "aarch64")]
pub use self::rtc_pl031::Rtc;
#[cfg(target_arch = "aarch64")]
pub use self::uart_pl011::Pl011;

View File

@@ -8,20 +8,20 @@
//! This is achieved by generating an interrupt signal after counting for a programmed number of cycles of
//! a real-time clock input.
//!
use crate::{read_le_u32, write_le_u32};
use std::fmt;
use std::sync::Arc;
use std::sync::{Arc, Barrier};
use std::time::Instant;
use std::{io, result};
use crate::BusDevice;
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
// As you can see in https://static.docs.arm.com/ddi0224/c/real_time_clock_pl031_r1p3_technical_reference_manual_DDI0224C.pdf
// at section 3.2 Summary of RTC registers, the total size occupied by this device is 0x000 -> 0xFFC + 4 = 0x1000.
// From 0x0 to 0x1C we have following registers:
const RTCDR: u64 = 0x0; // Data Register.
const RTCMR: u64 = 0x4; // Match Register.
const RTCLR: u64 = 0x8; // Load Regiser.
const RTCLR: u64 = 0x8; // Load Register.
const RTCCR: u64 = 0xc; // Control Register.
const RTCIMSC: u64 = 0x10; // Interrupt Mask Set or Clear Register.
const RTCRIS: u64 = 0x14; // Raw Interrupt Status.
@@ -39,52 +39,6 @@ const AMBA_ID_HIGH: u64 = 0x1000;
/// Constant to convert seconds to nanoseconds.
pub const NANOS_PER_SECOND: u64 = 1_000_000_000;
#[allow(unused_macros)]
macro_rules! generate_read_fn {
($fn_name: ident, $data_type: ty, $byte_type: ty, $type_size: expr, $endian_type: ident) => {
#[allow(dead_code)]
pub fn $fn_name(input: &[$byte_type]) -> $data_type {
assert!($type_size == std::mem::size_of::<$data_type>());
let mut array = [0u8; $type_size];
for (byte, read) in array.iter_mut().zip(input.iter().cloned()) {
*byte = read as u8;
}
<$data_type>::$endian_type(array)
}
};
}
#[allow(unused_macros)]
macro_rules! generate_write_fn {
($fn_name: ident, $data_type: ty, $byte_type: ty, $endian_type: ident) => {
#[allow(dead_code)]
pub fn $fn_name(buf: &mut [$byte_type], n: $data_type) {
for (byte, read) in buf
.iter_mut()
.zip(<$data_type>::$endian_type(n).iter().cloned())
{
*byte = read as $byte_type;
}
}
};
}
generate_read_fn!(read_le_u16, u16, u8, 2, from_le_bytes);
generate_read_fn!(read_le_u32, u32, u8, 4, from_le_bytes);
generate_read_fn!(read_le_u64, u64, u8, 8, from_le_bytes);
generate_read_fn!(read_le_i32, i32, i8, 4, from_le_bytes);
generate_read_fn!(read_be_u16, u16, u8, 2, from_be_bytes);
generate_read_fn!(read_be_u32, u32, u8, 4, from_be_bytes);
generate_write_fn!(write_le_u16, u16, u8, to_le_bytes);
generate_write_fn!(write_le_u32, u32, u8, to_le_bytes);
generate_write_fn!(write_le_u64, u64, u8, to_le_bytes);
generate_write_fn!(write_le_i32, i32, i8, to_le_bytes);
generate_write_fn!(write_be_u16, u16, u8, to_be_bytes);
generate_write_fn!(write_be_u32, u32, u8, to_be_bytes);
#[derive(Debug)]
pub enum Error {
BadWriteOffset(u64),
@@ -116,9 +70,9 @@ pub enum ClockType {
ThreadCpu,
}
impl Into<libc::clockid_t> for ClockType {
fn into(self) -> libc::clockid_t {
match self {
impl From<ClockType> for libc::clockid_t {
fn from(ct: ClockType) -> libc::clockid_t {
match ct {
ClockType::Monotonic => libc::CLOCK_MONOTONIC,
ClockType::Real => libc::CLOCK_REALTIME,
ClockType::ProcessCpu => libc::CLOCK_PROCESS_CPUTIME_ID,
@@ -261,7 +215,7 @@ pub fn seconds_to_nanoseconds(value: i64) -> Option<i64> {
}
/// A RTC device following the PL031 specification..
pub struct RTC {
pub struct Rtc {
previous_now: Instant,
tick_offset: i64,
// This is used for implementing the RTC alarm. However, in Firecracker we do not need it.
@@ -273,10 +227,10 @@ pub struct RTC {
interrupt: Arc<Box<dyn InterruptSourceGroup>>,
}
impl RTC {
impl Rtc {
/// Constructs an AMBA PL031 RTC device.
pub fn new(interrupt: Arc<Box<dyn InterruptSourceGroup>>) -> RTC {
RTC {
pub fn new(interrupt: Arc<Box<dyn InterruptSourceGroup>>) -> Self {
Self {
// This is used only for duration measuring purposes.
previous_now: Instant::now(),
tick_offset: get_time(ClockType::Real) as i64,
@@ -335,12 +289,12 @@ impl RTC {
}
}
impl BusDevice for RTC {
impl BusDevice for Rtc {
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
let v;
let mut read_ok = true;
if offset < AMBA_ID_HIGH && offset >= AMBA_ID_LOW {
if (AMBA_ID_LOW..AMBA_ID_HIGH).contains(&offset) {
let index = ((offset - AMBA_ID_LOW) >> 2) as usize;
v = u32::from(PL031_ID[index]);
} else {
@@ -372,9 +326,9 @@ impl BusDevice for RTC {
}
}
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) {
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
if data.len() <= 4 {
let v = read_le_u32(&data[..]);
let v = read_le_u32(&data);
if let Err(e) = self.handle_write(offset, v) {
warn!("Failed to write to RTC PL031 device: {}", e);
}
@@ -385,12 +339,18 @@ impl BusDevice for RTC {
data.len()
);
}
None
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
read_be_u16, read_be_u32, read_le_i32, read_le_u16, read_le_u32, read_le_u64, write_be_u16,
write_be_u32, write_le_i32, write_le_u16, write_le_u32, write_le_u64,
};
use std::sync::Arc;
use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig};
use vmm_sys_util::eventfd::EventFd;
@@ -475,8 +435,8 @@ mod tests {
Ok(())
}
fn notifier(&self, _index: InterruptIndex) -> Option<&EventFd> {
Some(&self.event_fd)
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
Some(self.event_fd.try_clone().unwrap())
}
}
@@ -490,7 +450,7 @@ mod tests {
fn test_rtc_read_write_and_event() {
let intr_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap();
let mut rtc = RTC::new(Arc::new(Box::new(TestInterrupt::new(
let mut rtc = Rtc::new(Arc::new(Box::new(TestInterrupt::new(
intr_evt.try_clone().unwrap(),
))));
let mut data = [0; 4];
@@ -499,7 +459,7 @@ mod tests {
write_le_u32(&mut data, 123);
rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCMR, &mut data);
rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCMR, &mut data);
let v = read_le_u32(&data[..]);
let v = read_le_u32(&data);
assert_eq!(v, 123);
// Read and write to the LR register.
@@ -511,7 +471,7 @@ mod tests {
assert!(rtc.previous_now > previous_now_before);
rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCLR, &mut data);
let v_read = read_le_u32(&data[..]);
let v_read = read_le_u32(&data);
assert_eq!((v / NANOS_PER_SECOND) as u32, v_read);
// Read and write to IMSC register.
@@ -522,14 +482,14 @@ mod tests {
// The interrupt line should be on.
assert!(rtc.interrupt.notifier(0).unwrap().read().unwrap() == 1);
rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &mut data);
let v = read_le_u32(&data[..]);
let v = read_le_u32(&data);
assert_eq!(non_zero & 1, v);
// Now test with 0.
write_le_u32(&mut data, 0);
rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &mut data);
rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &mut data);
let v = read_le_u32(&data[..]);
let v = read_le_u32(&data);
assert_eq!(0, v);
// Read and write to the ICR register.
@@ -537,10 +497,10 @@ mod tests {
rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCICR, &mut data);
// The interrupt line should be on.
assert!(rtc.interrupt.notifier(0).unwrap().read().unwrap() > 1);
let v_before = read_le_u32(&data[..]);
let v_before = read_le_u32(&data);
rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCICR, &mut data);
let v = read_le_u32(&data[..]);
let v = read_le_u32(&data);
// ICR is a write only register. Data received should stay equal to data sent.
assert_eq!(v, v_before);
@@ -548,7 +508,7 @@ mod tests {
write_le_u32(&mut data, 0);
rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCCR, &mut data);
rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCCR, &mut data);
let v = read_le_u32(&data[..]);
let v = read_le_u32(&data);
assert_eq!(v, 1);
// Attempts to write beyond the writable space. Using here the space used to read

View File

@@ -5,12 +5,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
use crate::BusDevice;
use anyhow::anyhow;
use std::collections::VecDeque;
use std::sync::Arc;
use std::sync::{Arc, Barrier};
use std::{io, result};
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, SnapshotDataSection, Snapshottable,
Transportable,
@@ -275,12 +275,14 @@ impl BusDevice for Serial {
};
}
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) {
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
if data.len() != 1 {
return;
return None;
}
if let Err(_e) = self.handle_write(offset as u8, data[0]) {}
self.handle_write(offset as u8, data[0]).ok();
None
}
}
@@ -289,7 +291,7 @@ impl Snapshottable for Serial {
self.id.clone()
}
fn snapshot(&self) -> std::result::Result<Snapshot, MigratableError> {
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
let snapshot =
serde_json::to_vec(&self.state()).map_err(|e| MigratableError::Snapshot(e.into()))?;
@@ -354,6 +356,9 @@ mod tests {
) -> result::Result<(), std::io::Error> {
Ok(())
}
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
Some(self.event_fd.try_clone().unwrap())
}
}
impl TestInterrupt {
@@ -394,13 +399,13 @@ mod tests {
Box::new(serial_out.clone()),
);
serial.write(0, DATA as u64, &['x' as u8, 'y' as u8]);
serial.write(0, DATA as u64, &['a' as u8]);
serial.write(0, DATA as u64, &['b' as u8]);
serial.write(0, DATA as u64, &['c' as u8]);
serial.write(0, DATA as u64, &[b'x', b'y']);
serial.write(0, DATA as u64, &[b'a']);
serial.write(0, DATA as u64, &[b'b']);
serial.write(0, DATA as u64, &[b'c']);
assert_eq!(
serial_out.buf.lock().unwrap().as_slice(),
&['a' as u8, 'b' as u8, 'c' as u8]
&[b'a', b'b', b'c']
);
}
@@ -411,16 +416,14 @@ mod tests {
let mut serial = Serial::new_out(
String::from(SERIAL_NAME),
Arc::new(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap()))),
Box::new(serial_out.clone()),
Box::new(serial_out),
);
// write 1 to the interrupt event fd, so that read doesn't block in case the event fd
// counter doesn't change (for 0 it blocks)
assert!(intr_evt.write(1).is_ok());
serial.write(0, IER as u64, &[IER_RECV_BIT]);
serial
.queue_input_bytes(&['a' as u8, 'b' as u8, 'c' as u8])
.unwrap();
serial.queue_input_bytes(&[b'a', b'b', b'c']).unwrap();
assert_eq!(intr_evt.read().unwrap(), 2);
@@ -433,11 +436,11 @@ mod tests {
serial.read(0, LSR as u64, &mut data[..]);
assert_ne!(data[0] & LSR_DATA_BIT, 0);
serial.read(0, DATA as u64, &mut data[..]);
assert_eq!(data[0], 'a' as u8);
assert_eq!(data[0], b'a');
serial.read(0, DATA as u64, &mut data[..]);
assert_eq!(data[0], 'b' as u8);
assert_eq!(data[0], b'b');
serial.read(0, DATA as u64, &mut data[..]);
assert_eq!(data[0], 'c' as u8);
assert_eq!(data[0], b'c');
// check if reading from the largest u8 offset returns 0
serial.read(0, 0xff, &mut data[..]);
@@ -456,7 +459,7 @@ mod tests {
// counter doesn't change (for 0 it blocks)
assert!(intr_evt.write(1).is_ok());
serial.write(0, IER as u64, &[IER_THR_BIT]);
serial.write(0, DATA as u64, &['a' as u8]);
serial.write(0, DATA as u64, &[b'a']);
assert_eq!(intr_evt.read().unwrap(), 2);
let mut data = [0u8];
@@ -474,13 +477,13 @@ mod tests {
Arc::new(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap()))),
);
serial.write(0, LCR as u64, &[LCR_DLAB_BIT as u8]);
serial.write(0, DLAB_LOW as u64, &[0x12 as u8]);
serial.write(0, DLAB_HIGH as u64, &[0x34 as u8]);
serial.write(0, LCR as u64, &[LCR_DLAB_BIT]);
serial.write(0, DLAB_LOW as u64, &[0x12]);
serial.write(0, DLAB_HIGH as u64, &[0x34]);
let mut data = [0u8];
serial.read(0, LCR as u64, &mut data[..]);
assert_eq!(data[0], LCR_DLAB_BIT as u8);
assert_eq!(data[0], LCR_DLAB_BIT);
serial.read(0, DLAB_LOW as u64, &mut data[..]);
assert_eq!(data[0], 0x12);
serial.read(0, DLAB_HIGH as u64, &mut data[..]);
@@ -495,22 +498,22 @@ mod tests {
Arc::new(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap()))),
);
serial.write(0, MCR as u64, &[MCR_LOOP_BIT as u8]);
serial.write(0, DATA as u64, &['a' as u8]);
serial.write(0, DATA as u64, &['b' as u8]);
serial.write(0, DATA as u64, &['c' as u8]);
serial.write(0, MCR as u64, &[MCR_LOOP_BIT]);
serial.write(0, DATA as u64, &[b'a']);
serial.write(0, DATA as u64, &[b'b']);
serial.write(0, DATA as u64, &[b'c']);
let mut data = [0u8];
serial.read(0, MSR as u64, &mut data[..]);
assert_eq!(data[0], DEFAULT_MODEM_STATUS as u8);
assert_eq!(data[0], DEFAULT_MODEM_STATUS);
serial.read(0, MCR as u64, &mut data[..]);
assert_eq!(data[0], MCR_LOOP_BIT as u8);
assert_eq!(data[0], MCR_LOOP_BIT);
serial.read(0, DATA as u64, &mut data[..]);
assert_eq!(data[0], 'a' as u8);
assert_eq!(data[0], b'a');
serial.read(0, DATA as u64, &mut data[..]);
assert_eq!(data[0], 'b' as u8);
assert_eq!(data[0], b'b');
serial.read(0, DATA as u64, &mut data[..]);
assert_eq!(data[0], 'c' as u8);
assert_eq!(data[0], b'c');
}
#[test]
@@ -521,10 +524,10 @@ mod tests {
Arc::new(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap()))),
);
serial.write(0, SCR as u64, &[0x12 as u8]);
serial.write(0, SCR as u64, &[0x12]);
let mut data = [0u8];
serial.read(0, SCR as u64, &mut data[..]);
assert_eq!(data[0], 0x12 as u8);
assert_eq!(data[0], 0x12);
}
}

View File

@@ -0,0 +1,506 @@
// Copyright 2021 Arm Limited (or its affiliates). All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//! ARM PrimeCell UART(PL011)
//!
//! This module implements an ARM PrimeCell UART(PL011).
//!
use crate::{read_le_u32, write_le_u32};
use anyhow::anyhow;
use std::collections::VecDeque;
use std::fmt;
use std::sync::{Arc, Barrier};
use std::{io, result};
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, SnapshotDataSection, Snapshottable,
Transportable,
};
/* Registers */
const UARTDR: u64 = 0;
const UARTRSR_UARTECR: u64 = 1;
const UARTFR: u64 = 6;
const UARTILPR: u64 = 8;
const UARTIBRD: u64 = 9;
const UARTFBRD: u64 = 10;
const UARTLCR_H: u64 = 11;
const UARTCR: u64 = 12;
const UARTIFLS: u64 = 13;
const UARTIMSC: u64 = 14;
const UARTRIS: u64 = 15;
const UARTMIS: u64 = 16;
const UARTICR: u64 = 17;
const UARTDMACR: u64 = 18;
const PL011_INT_TX: u32 = 0x20;
const PL011_INT_RX: u32 = 0x10;
const PL011_FLAG_RXFF: u32 = 0x40;
const PL011_FLAG_RXFE: u32 = 0x10;
const PL011_ID: [u8; 8] = [0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
// We are only interested in the margins.
const AMBA_ID_LOW: u64 = 0x3f8;
const AMBA_ID_HIGH: u64 = 0x401;
#[derive(Debug)]
pub enum Error {
BadWriteOffset(u64),
DmaNotImplemented,
InterruptFailure(io::Error),
WriteAllFailure(io::Error),
FlushFailure(io::Error),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::BadWriteOffset(offset) => write!(f, "pl011_write: Bad Write Offset: {}", offset),
Error::DmaNotImplemented => write!(f, "pl011: DMA not implemented."),
Error::InterruptFailure(e) => write!(f, "Failed to trigger interrupt: {}", e),
Error::WriteAllFailure(e) => write!(f, "Failed to write: {}", e),
Error::FlushFailure(e) => write!(f, "Failed to flush: {}", e),
}
}
}
type Result<T> = result::Result<T, Error>;
/// A PL011 device following the PL011 specification.
pub struct Pl011 {
id: String,
flags: u32,
lcr: u32,
rsr: u32,
cr: u32,
dmacr: u32,
int_enabled: u32,
int_level: u32,
read_fifo: VecDeque<u8>,
ilpr: u32,
ibrd: u32,
fbrd: u32,
ifl: u32,
read_count: u32,
read_trigger: u32,
irq: Arc<Box<dyn InterruptSourceGroup>>,
out: Option<Box<dyn io::Write + Send>>,
}
#[derive(Serialize, Deserialize)]
pub struct Pl011State {
flags: u32,
lcr: u32,
rsr: u32,
cr: u32,
dmacr: u32,
int_enabled: u32,
int_level: u32,
read_fifo: VecDeque<u8>,
ilpr: u32,
ibrd: u32,
fbrd: u32,
ifl: u32,
read_count: u32,
read_trigger: u32,
}
impl Pl011 {
/// Constructs an AMBA PL011 UART device.
pub fn new(
id: String,
irq: Arc<Box<dyn InterruptSourceGroup>>,
out: Option<Box<dyn io::Write + Send>>,
) -> Self {
Self {
id,
flags: 0x90u32,
lcr: 0u32,
rsr: 0u32,
cr: 0x300u32,
dmacr: 0u32,
int_enabled: 0u32,
int_level: 0u32,
read_fifo: VecDeque::new(),
ilpr: 0u32,
ibrd: 0u32,
fbrd: 0u32,
ifl: 0x12u32,
read_count: 0u32,
read_trigger: 1u32,
irq,
out,
}
}
fn state(&self) -> Pl011State {
Pl011State {
flags: self.flags,
lcr: self.lcr,
rsr: self.rsr,
cr: self.cr,
dmacr: self.dmacr,
int_enabled: self.int_enabled,
int_level: self.int_level,
read_fifo: self.read_fifo.clone(),
ilpr: self.ilpr,
ibrd: self.ibrd,
fbrd: self.fbrd,
ifl: self.ifl,
read_count: self.read_count,
read_trigger: self.read_trigger,
}
}
fn set_state(&mut self, state: &Pl011State) {
self.flags = state.flags;
self.lcr = state.lcr;
self.rsr = state.rsr;
self.cr = state.cr;
self.dmacr = state.dmacr;
self.int_enabled = state.int_enabled;
self.int_level = state.int_level;
self.read_fifo = state.read_fifo.clone();
self.ilpr = state.ilpr;
self.ibrd = state.ibrd;
self.fbrd = state.fbrd;
self.ifl = state.ifl;
self.read_count = state.read_count;
self.read_trigger = state.read_trigger;
}
/// Queues raw bytes for the guest to read and signals the interrupt
pub fn queue_input_bytes(&mut self, c: &[u8]) -> vmm_sys_util::errno::Result<()> {
self.read_fifo.extend(c);
self.read_count += c.len() as u32;
self.flags &= !PL011_FLAG_RXFE;
if ((self.lcr & 0x10) == 0) || (self.read_count == 16) {
self.flags |= PL011_FLAG_RXFF;
}
if self.read_count >= self.read_trigger {
self.int_level |= PL011_INT_RX;
self.trigger_interrupt()?;
}
Ok(())
}
fn pl011_get_baudrate(&self) -> u32 {
if self.fbrd == 0 {
return 0;
}
let clk = 24_000_000; // We set the APB_PLCK to 24M in device tree
(clk / ((self.ibrd << 6) + self.fbrd)) << 2
}
fn pl011_trace_baudrate_change(&self) {
debug!(
"=== New baudrate: {:#?} (clk: {:#?}Hz, ibrd: {:#?}, fbrd: {:#?}) ===",
self.pl011_get_baudrate(),
24_000_000, // We set the APB_PLCK to 24M in device tree
self.ibrd,
self.fbrd
);
}
fn pl011_set_read_trigger(&mut self) {
self.read_trigger = 1;
}
fn handle_write(&mut self, offset: u64, val: u32) -> Result<()> {
match offset >> 2 {
UARTDR => {
self.int_level |= PL011_INT_TX;
if let Some(out) = self.out.as_mut() {
out.write_all(&[val.to_le_bytes()[0]])
.map_err(Error::WriteAllFailure)?;
out.flush().map_err(Error::FlushFailure)?;
}
}
UARTRSR_UARTECR => {
self.rsr = 0;
}
UARTFR => { /* Writes to Flag register are ignored.*/ }
UARTILPR => {
self.ilpr = val;
}
UARTIBRD => {
self.ibrd = val;
self.pl011_trace_baudrate_change();
}
UARTFBRD => {
self.fbrd = val;
self.pl011_trace_baudrate_change();
}
UARTLCR_H => {
/* Reset the FIFO state on FIFO enable or disable */
if ((self.lcr ^ val) & 0x10) != 0 {
self.read_count = 0;
}
self.lcr = val;
self.pl011_set_read_trigger();
}
UARTCR => {
self.cr = val;
}
UARTIFLS => {
self.ifl = val;
self.pl011_set_read_trigger();
}
UARTIMSC => {
self.int_enabled = val;
self.trigger_interrupt().map_err(Error::InterruptFailure)?;
}
UARTICR => {
self.int_level &= !val;
self.trigger_interrupt().map_err(Error::InterruptFailure)?;
}
UARTDMACR => {
self.dmacr = val;
if (val & 3) != 0 {
return Err(Error::DmaNotImplemented);
}
}
off => {
return Err(Error::BadWriteOffset(off));
}
}
Ok(())
}
fn trigger_interrupt(&mut self) -> result::Result<(), io::Error> {
self.irq.trigger(0)
}
}
impl BusDevice for Pl011 {
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
let v;
let mut read_ok = true;
if (AMBA_ID_LOW..AMBA_ID_HIGH).contains(&(offset >> 2)) {
let index = ((offset - 0xfe0) >> 2) as usize;
v = u32::from(PL011_ID[index]);
} else {
v = match offset >> 2 {
UARTDR => {
let c: u32;
let r: u32;
self.flags &= !PL011_FLAG_RXFF;
c = self.read_fifo.pop_front().unwrap_or_default().into();
if self.read_count > 0 {
self.read_count -= 1;
}
if self.read_count == 0 {
self.flags |= PL011_FLAG_RXFE;
}
if self.read_count == (self.read_trigger - 1) {
self.int_level &= !PL011_INT_RX;
}
self.rsr = c >> 8;
r = c;
r
}
UARTRSR_UARTECR => self.rsr,
UARTFR => self.flags,
UARTILPR => self.ilpr,
UARTIBRD => self.ibrd,
UARTFBRD => self.fbrd,
UARTLCR_H => self.lcr,
UARTCR => self.cr,
UARTIFLS => self.ifl,
UARTIMSC => self.int_enabled,
UARTRIS => self.int_level,
UARTMIS => (self.int_level & self.int_enabled),
UARTDMACR => self.dmacr,
_ => {
read_ok = false;
0
}
}
}
if read_ok && data.len() <= 4 {
write_le_u32(data, v);
} else {
warn!(
"Invalid PL011 read: offset {}, data length {}",
offset,
data.len()
);
}
}
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
if data.len() <= 4 {
let v = read_le_u32(&data);
if let Err(e) = self.handle_write(offset, v) {
warn!("Failed to write to PL011 device: {}", e);
}
} else {
warn!(
"Invalid PL011 write: offset {}, data length {}",
offset,
data.len()
);
}
None
}
}
impl Snapshottable for Pl011 {
fn id(&self) -> String {
self.id.clone()
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
let snapshot =
serde_json::to_vec(&self.state()).map_err(|e| MigratableError::Snapshot(e.into()))?;
let mut pl011_snapshot = Snapshot::new(self.id.as_str());
pl011_snapshot.add_data_section(SnapshotDataSection {
id: format!("{}-section", self.id),
snapshot,
});
Ok(pl011_snapshot)
}
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
if let Some(pl011_section) = snapshot.snapshot_data.get(&format!("{}-section", self.id)) {
let pl011_state = match serde_json::from_slice(&pl011_section.snapshot) {
Ok(state) => state,
Err(error) => {
return Err(MigratableError::Restore(anyhow!(
"Could not deserialize PL011 {}",
error
)))
}
};
self.set_state(&pl011_state);
return Ok(());
}
Err(MigratableError::Restore(anyhow!(
"Could not find the PL011 snapshot section"
)))
}
}
impl Pausable for Pl011 {}
impl Transportable for Pl011 {}
impl Migratable for Pl011 {}
#[cfg(test)]
mod tests {
use super::*;
use std::io;
use std::sync::{Arc, Mutex};
use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig};
use vmm_sys_util::eventfd::EventFd;
const SERIAL_NAME: &str = "serial";
struct TestInterrupt {
event_fd: EventFd,
}
impl InterruptSourceGroup for TestInterrupt {
fn trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error> {
self.event_fd.write(1)
}
fn update(
&self,
_index: InterruptIndex,
_config: InterruptSourceConfig,
) -> result::Result<(), std::io::Error> {
Ok(())
}
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
Some(self.event_fd.try_clone().unwrap())
}
}
impl TestInterrupt {
fn new(event_fd: EventFd) -> Self {
TestInterrupt { event_fd }
}
}
#[derive(Clone)]
struct SharedBuffer {
buf: Arc<Mutex<Vec<u8>>>,
}
impl SharedBuffer {
fn new() -> SharedBuffer {
SharedBuffer {
buf: Arc::new(Mutex::new(Vec::new())),
}
}
}
impl io::Write for SharedBuffer {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.buf.lock().unwrap().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.buf.lock().unwrap().flush()
}
}
#[test]
fn pl011_output() {
let intr_evt = EventFd::new(0).unwrap();
let pl011_out = SharedBuffer::new();
let mut pl011 = Pl011::new(
String::from(SERIAL_NAME),
Arc::new(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap()))),
Some(Box::new(pl011_out.clone())),
);
pl011.write(0, UARTDR as u64, &[b'x', b'y']);
pl011.write(0, UARTDR as u64, &[b'a']);
pl011.write(0, UARTDR as u64, &[b'b']);
pl011.write(0, UARTDR as u64, &[b'c']);
assert_eq!(
pl011_out.buf.lock().unwrap().as_slice(),
&[b'x', b'a', b'b', b'c']
);
}
#[test]
fn pl011_input() {
let intr_evt = EventFd::new(0).unwrap();
let pl011_out = SharedBuffer::new();
let mut pl011 = Pl011::new(
String::from(SERIAL_NAME),
Arc::new(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap()))),
Some(Box::new(pl011_out)),
);
// write 1 to the interrupt event fd, so that read doesn't block in case the event fd
// counter doesn't change (for 0 it blocks)
assert!(intr_evt.write(1).is_ok());
pl011.queue_input_bytes(&[b'a', b'b', b'c']).unwrap();
assert_eq!(intr_evt.read().unwrap(), 2);
let mut data = [0u8];
pl011.read(0, UARTDR as u64, &mut data);
assert_eq!(data[0], b'a');
pl011.read(0, UARTDR as u64, &mut data);
assert_eq!(data[0], b'b');
pl011.read(0, UARTDR as u64, &mut data);
assert_eq!(data[0], b'c');
}
}

View File

@@ -25,12 +25,8 @@ extern crate vmm_sys_util;
extern crate serde_derive;
extern crate serde_json;
use std::fs::File;
use std::io;
#[cfg(feature = "acpi")]
mod acpi;
mod bus;
pub mod acpi;
#[cfg(target_arch = "aarch64")]
pub mod gic;
pub mod interrupt_controller;
@@ -39,52 +35,74 @@ pub mod ioapic;
pub mod legacy;
#[cfg(feature = "acpi")]
pub use self::acpi::{AcpiGEDDevice, AcpiShutdownDevice};
pub use self::bus::{Bus, BusDevice, Error as BusError};
pub type DeviceEventT = u16;
/// The payload is used to handle events where the internal state of the VirtIO device
/// needs to be changed.
pub enum EpollHandlerPayload {
/// DrivePayload(disk_image)
DrivePayload(File),
/// Events that do not need a payload.
Empty,
}
type Result<T> = std::result::Result<T, Error>;
pub trait EpollHandler: Send {
fn handle_event(
&mut self,
device_event: DeviceEventT,
event_flags: u32,
payload: EpollHandlerPayload,
) -> Result<()>;
}
#[derive(Debug)]
pub enum Error {
FailedReadingQueue {
event_type: &'static str,
underlying: io::Error,
},
FailedReadTap,
FailedSignalingUsedQueue(io::Error),
PayloadExpected,
UnknownEvent {
device: &'static str,
event: DeviceEventT,
},
IoError(io::Error),
}
pub use self::acpi::{AcpiGedDevice, AcpiPmTimerDevice, AcpiShutdownDevice};
bitflags! {
pub struct HotPlugNotificationFlags: u8 {
pub struct AcpiNotificationFlags: u8 {
const NO_DEVICES_CHANGED = 0;
const CPU_DEVICES_CHANGED = 0b1;
const MEMORY_DEVICES_CHANGED = 0b10;
const PCI_DEVICES_CHANGED = 0b100;
const POWER_BUTTON_CHANGED = 0b1000;
}
}
#[allow(unused_macros)]
#[cfg(target_arch = "aarch64")]
macro_rules! generate_read_fn {
($fn_name: ident, $data_type: ty, $byte_type: ty, $type_size: expr, $endian_type: ident) => {
#[allow(dead_code)]
pub fn $fn_name(input: &[$byte_type]) -> $data_type {
assert!($type_size == std::mem::size_of::<$data_type>());
let mut array = [0u8; $type_size];
for (byte, read) in array.iter_mut().zip(input.iter().cloned()) {
*byte = read as u8;
}
<$data_type>::$endian_type(array)
}
};
}
#[allow(unused_macros)]
#[cfg(target_arch = "aarch64")]
macro_rules! generate_write_fn {
($fn_name: ident, $data_type: ty, $byte_type: ty, $endian_type: ident) => {
#[allow(dead_code)]
pub fn $fn_name(buf: &mut [$byte_type], n: $data_type) {
for (byte, read) in buf
.iter_mut()
.zip(<$data_type>::$endian_type(n).iter().cloned())
{
*byte = read as $byte_type;
}
}
};
}
#[cfg(target_arch = "aarch64")]
generate_read_fn!(read_le_u16, u16, u8, 2, from_le_bytes);
#[cfg(target_arch = "aarch64")]
generate_read_fn!(read_le_u32, u32, u8, 4, from_le_bytes);
#[cfg(target_arch = "aarch64")]
generate_read_fn!(read_le_u64, u64, u8, 8, from_le_bytes);
#[cfg(target_arch = "aarch64")]
generate_read_fn!(read_le_i32, i32, i8, 4, from_le_bytes);
#[cfg(target_arch = "aarch64")]
generate_read_fn!(read_be_u16, u16, u8, 2, from_be_bytes);
#[cfg(target_arch = "aarch64")]
generate_read_fn!(read_be_u32, u32, u8, 4, from_be_bytes);
#[cfg(target_arch = "aarch64")]
generate_write_fn!(write_le_u16, u16, u8, to_le_bytes);
#[cfg(target_arch = "aarch64")]
generate_write_fn!(write_le_u32, u32, u8, to_le_bytes);
#[cfg(target_arch = "aarch64")]
generate_write_fn!(write_le_u64, u64, u8, to_le_bytes);
#[cfg(target_arch = "aarch64")]
generate_write_fn!(write_le_i32, i32, i8, to_le_bytes);
#[cfg(target_arch = "aarch64")]
generate_write_fn!(write_be_u16, u16, u8, to_be_bytes);
#[cfg(target_arch = "aarch64")]
generate_write_fn!(write_be_u32, u32, u8, to_be_bytes);

View File

@@ -12,7 +12,7 @@
* [Reboot a Virtual Machine](#reboot-a-virtual-machine)
* [Shut a Virtual Machine Down](#shut-a-virtual-machine-down)
+ [Command Line Interface](#command-line-interface)
+ [REST API and CLI Architecural Relationship](#rest-api-and-cli-architectural-relationship)
+ [REST API and CLI Architectural Relationship](#rest-api-and-cli-architectural-relationship)
* [Internal API](#internal-api)
+ [Goals and Design](#goals-and-design)
* [End to End Example](#end-to-end-example)
@@ -78,25 +78,27 @@ Shut the VMM down | `/vmm.shutdown` | N/A | N/A
#### 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
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
Add/remove CPUs to/from the VM | `/vm.resize` | `/schemas/VmResize` | N/A | The VM is booted
Remove memory from the VM | `/vm.resize` | `/schemas/VmResize` | 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` | N/A | The VM is booted
Remove VFIO PCI device from the VM | `/vm.remove-device` | `/schemas/VmRemoveDevice` | N/A | The VM is booted
Add disk device to the VM | `/vm.add-disk` | `/schemas/DiskConfig` | N/A | The VM is booted
Add fs device to the VM | `/vm.add-fs` | `/schemas/FsConfig` | N/A | The VM is booted
Add pmem device to the VM | `/vm.add-pmem` | `/schemas/PmemConfig` | N/A | The VM is booted
Add network device to the VM | `/vm.add-net` | `/schemas/NetConfig` | N/A | The VM is booted
Add vsock device to the VM | `/vm.add-vsock` | `/schemas/VsockConfig` | N/A | 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
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
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 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
### REST API Examples
@@ -121,10 +123,10 @@ We want to create a virtual machine with the following characteristics:
* 4 vCPUs
* 1 GB of RAM
* 1 virtio based networking interface
* Direct kernel boot from a custom 5.5.0 Linux kernel located at
* Direct kernel boot from a custom 5.6.0-rc4 Linux kernel located at
`/opt/clh/kernel/vmlinux-virtio-fs-virtio-iommu`
* Using a Clear Linux image as its root filesystem, located at
`/opt/clh/images/clear-30080-kvm.img`
* Using a Ubuntu image as its root filesystem, located at
`/opt/clh/images/focal-server-cloudimg-amd64.raw`
```shell
#!/bin/bash
@@ -136,8 +138,8 @@ curl --unix-socket /tmp/cloud-hypervisor.sock -i \
-d '{
"cpus":{"boot_vcpus": 4, "max_vcpus": 4},
"kernel":{"path":"/opt/clh/kernel/vmlinux-virtio-fs-virtio-iommu"},
"cmdline":{"args":"console=hvc0 reboot=k panic=1 nomodules i8042.noaux i8042.nomux i8042.nopnp i8042.dumbkbd root=/dev/vda3"},
"disks":[{"path":"/opt/clh/images/clear-30080-kvm.img"}],
"cmdline":{"args":"console=ttyS0 console=hvc0 root=/dev/vda1 rw"},
"disks":[{"path":"/opt/clh/images/focal-server-cloudimg-amd64.raw"}],
"rng":{"src":"/dev/urandom"},
"net":[{"ip":"192.168.10.10", "mask":"255.255.255.0", "mac":"12:34:56:78:90:01"}]
}'
@@ -304,8 +306,8 @@ APIs work together, let's look at a complete VM creation flow, from the
-d '{
"cpus":{"boot_vcpus": 4, "max_vcpus": 4},
"kernel":{"path":"/opt/clh/kernel/vmlinux-virtio-fs-virtio-iommu"},
"cmdline":{"args":"console=hvc0 reboot=k panic=1 nomodules i8042.noaux i8042.nomux i8042.nopnp i8042.dumbkbd root=/dev/vda3"},
"disks":[{"path":"/opt/clh/images/clear-30080-kvm.img"}],
"cmdline":{"args":"console=ttyS0 console=hvc0 root=/dev/vda1 rw"},
"disks":[{"path":"/opt/clh/images/focal-server-cloudimg-amd64.raw"}],
"rng":{"src":"/dev/urandom"},
"net":[{"ip":"192.168.10.10", "mask":"255.255.255.0", "mac":"12:34:56:78:90:01"}]
}'

View File

@@ -1,11 +1,11 @@
# How to build and run Cloud-hypervisor on Arm64
# How to build and run Cloud-hypervisor on AArch64
Cloud-hypervisor is partially enabled on AArch64 architecture.
Although all features are not ready yet, you can begin to test Cloud-hypervisor on a Arm64 host by following this guide.
Although all features are not ready yet, you can begin to test Cloud-hypervisor on a AArch64 host by following this guide.
## Prerequisites
On Arm64 machines, Cloud-hypervisor depends on an external library `libfdt-dev` for generating Flatted Device Tree (FDT).
On AArch64 machines, Cloud-hypervisor depends on an external library `libfdt-dev` for generating Flattened Device Tree (FDT).
The long-term plan is to replace `libfdt-dev` with some pure-Rust component to get rid of such dependency.
@@ -16,16 +16,10 @@ sudo apt-get install libfdt-dev
## Build
Before building, a hack trick need to be performed to get rid of some build error in vmm component. See [this](https://github.com/cloud-hypervisor/kvm-bindings/pull/1) for more info about this temporary workaround.
Using PCI devices requires GICv3-ITS for MSI messaging. GICv3-ITS is very common in modern servers.
```bash
sed -i 's/"with-serde",\ //g' vmm/Cargo.toml
```
The support of AArch64 is in very early stage, only Virtio devices with MMIO tranport is available.
```bash
cargo build --no-default-features --features "mmio"
cargo build --no-default-features --features kvm
```
## Image
@@ -33,7 +27,7 @@ cargo build --no-default-features --features "mmio"
Download kernel binary and rootfs image from AWS.
```bash
wget https://s3.amazonaws.com/spec.ccfc.min/img/aarch64/ubuntu_with_ssh/fsfiles/xenial.rootfs.ext4 -O rootfs.img
wget https://s3.amazonaws.com/spec.ccfc.min/img/aarch64/ubuntu_with_ssh/fsfiles/xenial.rootfs.ext4 -O rootfs.ext4
wget https://s3.amazonaws.com/spec.ccfc.min/img/aarch64/ubuntu_with_ssh/kernel/vmlinux.bin -O kernel.bin
```
@@ -58,7 +52,7 @@ To build Cloud-hypervisor in the container:
Assuming you have built Cloud-hypervisor with the development container, a VM can be started with command:
```bash
sudo target/debug/cloud-hypervisor --kernel kernel.bin --disk path=rootfs.ext4 --cmdline "keep_bootcon console=hvc0 reboot=k panic=1 pci=off root=/dev/vda rw" --cpus boot=4 --memory size=512M --seccomp false --serial file=serial.log --log-file log.log -vvv
sudo build/cargo_target/aarch64-unknown-linux-gnu/debug/cloud-hypervisor --kernel kernel.bin --disk path=rootfs.ext4 --cmdline "keep_bootcon console=hvc0 reboot=k panic=1 root=/dev/vda rw" --cpus boot=4 --memory size=512M --serial file=serial.log --log-file log.log -vvv
```
If the build was done out of the container, replace the binary path with `build/cargo_target/aarch64-unknown-linux-gnu/debug/cloud-hypervisor`.
If the build was done out of the container, replace the binary path with `target/debug/cloud-hypervisor`.

View File

@@ -1,96 +1,149 @@
# How to create a custom Clear Linux image
# How to create a custom Ubuntu image
In the context of adding more utility to the cloudguest image being used
for integration testing, this is a quick guide on how to achieve the creation
of your own Clear Linux image using the official Clear Linux tooling.
## Prepare the environment
From the host, the goal is run a Clear Linux VM that will allow us to build
the custom image we want.
```bash
# Get latest CL version:
IMG_VERSION=$(curl https://download.clearlinux.org/latest)
# Get latest clear-kvm image:
wget -P $HOME/workloads/ https://download.clearlinux.org/current/clear-${IMG_VERSION}-kvm.img.xz
# Extract the image
unxz $HOME/workloads/clear-${IMG_VERSION}-kvm.img.xz
# Make sure cloud-hypervisor binary has CAP_NET_ADMIN capability set
sudo setcap cap_net_admin+ep cloud-hypervisor
# Boot cloud-hypervisor VM with the downloaded image
./cloud-hypervisor -v --kernel $HOME/workloads/vmlinux --disk path=clear-${IMG_VERSION}-kvm.img --cmdline "console=ttyS0 console=hvc0 reboot=k panic=1 nomodules root=/dev/vda3 rw" --cpus 1 --memory size=4G --net tap=,mac=
# Setup connectivity
# First make sure to enable IP forwarding (disabled on Linux by default)
sudo bash -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
# Retrieve the interface name and the gateway IP
IFACE=$(ip route | grep default | awk -F 'dev' '{print $2}' | awk -F ' ' '{print $1}')
GW=$(ip route | grep vmtap0 | awk -F ' ' '{print $1}')
# Create a new masquerade rule to tag the packets going out
sudo iptables -t nat -A POSTROUTING -s ${GW} -o ${IFACE} -j MASQUERADE
```
In the context of adding more utilities to the Ubuntu cloud image being used
for integration testing, this quick guide details how to achieve the proper
modification of an official Ubuntu cloud image.
## Create the image
From the guest, we can now create the image.
Let's go through the steps on how to extend an official Ubuntu image. These
steps can be applied to other distributions (with a few changes regarding
package management).
### Get latest Ubuntu cloud image
```bash
# Setup connectivity
sudo ip addr add 192.168.249.2/24 dev enp0s3
sudo ip route add default via 192.168.249.1
# Install necessary bundles
sudo swupd bundle-add clr-installer
sudo swupd bundle-add os-installer
# Download and update cloudguest image configuration
wget https://download.clearlinux.org/current/config/image/cloudguest.yaml
sed -i '/size: \"864M\"/d' cloudguest.yaml
sed -i 's/\"800M\"/\"2G\"/g' cloudguest.yaml
sed -i 's/bootloader,/bootloader,\n curl,\n iperf,/g' cloudguest.yaml
sed -i 's/systemd-networkd-autostart/sysadmin-basic,\n systemd-networkd-autostart/g' cloudguest.yaml
# Create the custom cloudguest image
clr-installer -c cloudguest.yaml
# Make the guest accessible through ssh
sudo mkdir -p /etc/ssh
sudo bash -c "echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config"
wget https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img
```
### Retrieve the image
Once the new image has been created and the guest is accessible through
`ssh`, it is time to retrieve the image from the host.
### Check the file format is QCOW2
```bash
# Retrieve new image (this is a raw image)
scp root@192.168.249.2:cloudguest.img .
mv cloudguest.img clear-cloudguest-raw.img
# Create the QCOW image from the RAW image
qemu-img convert -p -f raw -O qcow2 clear-cloudguest-raw.img clear-cloudguest.img
# Compress the QCOW image
xz -k -T $(nproc) clear-cloudguest.img
file focal-server-cloudimg-amd64.img
focal-server-cloudimg-amd64.img: QEMU QCOW2 Image (v2), 2361393152 bytes
```
### Convert QCOW2 into RAW
```bash
qemu-img convert -p -f qcow2 -O raw focal-server-cloudimg-amd64.img focal-server-cloudimg-amd64.raw
```
### Identify the Linux partition
The goal is to mount the image rootfs so that it can be modified as needed.
That's why we need to identify where the Linux filesystem partition is located
in the image.
```bash
sudo fdisk -l focal-server-cloudimg-amd64.raw
Disk focal-server-cloudimg-amd64.raw: 2.2 GiB, 2361393152 bytes, 4612096 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: A1171ABA-2BEA-4218-A467-1B2B607E5953
Device Start End Sectors Size Type
focal-server-cloudimg-amd64.raw1 227328 4612062 4384735 2.1G Linux filesystem
focal-server-cloudimg-amd64.raw14 2048 10239 8192 4M BIOS boot
focal-server-cloudimg-amd64.raw15 10240 227327 217088 106M EFI System
Partition table entries are not in disk order.
```
### Mount the Linux partition
```bash
mkdir -p /mnt
sudo mount -o loop,offset=$((227328 * 512)) focal-server-cloudimg-amd64.raw /mnt
```
### Change root directory
Changing the root directory will allow us to install new packages to the rootfs
contained by the cloud image.
```bash
sudo chroot /mnt
mount -t proc proc /proc
mount -t devpts devpts /dev/pts
```
### Install needed packages
In the context Cloud-Hypervisor's integration tests, we need several utilities.
Here is the way to install them for a Ubuntu image. This step is specific to
Ubuntu distributions.
```bash
apt update
apt install fio iperf iperf3 socat
```
### Remove counterproductive packages
* snapd:
This prevents snapd from trying to mount squashfs filesystem when the kernel
might not support it. This might be the case when the image is used with direct
kernel boot. This step is specific to Ubuntu distributions.
* pollinate:
Remove this package which can fail and lead to the SSH daemon failing to start.
See #2113 for details.
```bash
apt remove --purge snapd pollinate
```
### Cleanup the image
Leave no trace in the image before unmounting its content.
```bash
umount /dev/pts
umount /proc
history -c
exit
umount /mnt
```
### Rename the image
Renaming is important to identify this is a modified image.
```bash
mv focal-server-cloudimg-amd64.raw focal-server-cloudimg-amd64-custom-$(date "+%Y%m%d")-0.raw
```
The `-0` is the revision and is only necessary to change if multiple images are
updated on the same day.
### Create QCOW2 from RAW
Last step is to create the QCOW2 image back from the modified image.
```bash
qemu-img convert -p -f raw -O qcow2 focal-server-cloudimg-amd64-custom-$(date "+%Y%m%d")-0.raw focal-server-cloudimg-amd64-custom-$(date "+%Y%m%d")-0.qcow2
```
## Switch CI to use the new image
### Upload to Azure storage
The next step is to update the image stored as part of the Azure storage
account, replacing it with the newly created image. This will make this
new image available from the integration tests.
This is usually achieved through the web interface.
The next step is to update both images (QCOW2 and RAW) stored as part of the
Azure storage account, replacing them with the newly created ones. This will
make these new images available from the integration tests. This is usually
achieved through the web interface.
### Update integration tests
Last step is about updating the integration tests to work with this new image.
The key point is to identify the UUID of this new image so that it can be used
directly from the tests.
The key point is to identify where the Linux filesystem partition is located,
as we might need to update the direct kernel boot command line, replacing
`/dev/vda1` with the appropriate partition number.
Proceed as follow to determine this UUID:
```bash
# Mount the image
sudo mount -o loop,offset=$((2048 * 512)) clear-cloudguest-raw.img /mnt/
# Identify UUID
sudo cat /mnt/loader/entries/Clear-linux-kvm-*.conf | grep "root=PARTUUID="
# Unmount the image
sudo umount /mnt
```
Update all references to the previous image name to the new one.

View File

@@ -43,7 +43,7 @@ to easily grep for the tracing logs (e.g.
```
./target/debug/cloud-hypervisor \
--kernel ~/rust-hypervisor-firmware/target/target/release/hypervisor-fw \
--disk path=~/hypervisor/images/clear-30080-kvm.img \
--disk path=~/hypervisor/images/focal-server-cloudimg-amd64.raw \
--cpus 4 \
--memory size=1024M \
--rng \

View File

@@ -28,9 +28,13 @@ This document describes the device model supported by `cloud-hypervisor`.
### Serial port
Simple emulation of a serial port by reading and writing to specific port I/O
addresses. Used as the default console for Linux when booting with the option
`console=ttyS0`, the serial port can be very useful to gather early logs from
the operating system booted inside the VM.
addresses. The serial port can be very useful to gather early logs from the
operating system booted inside the VM.
For x86_64, The default serial port is from an emulated 16550A device. It can
be used as the default console for Linux when booting with the option
`console=ttyS0`. For AArch64, the default serial port is from an emulated
PL011 UART device. The related command line for AArch64 is `console=ttyAMA0`.
This device is always built-in, and it is disabled by default. It can be
enabled with the `--serial` option, as long as its parameter is not `off`.
@@ -44,6 +48,10 @@ This device is built-in by default, but it can be compiled out with Rust
features. When compiled in, it is always enabled, and cannot be disabled
from the command line.
For AArch64 machines, an ARM PrimeCell Real Time Clock(PL031) is implemented.
This device is built-in by default for the AArch64 platform, and it is always
enabled, and cannot be disabled from the command line.
### I/O APIC
`cloud-hypervisor` supports a so-called split IRQ chip implementation by
@@ -65,6 +73,11 @@ enabled by default, the handling of reboot/shutdown goes through the dedicated
ACPI device. In case ACPI is disabled, this device is enabled to bring to the
VM some reboot/shutdown support.
### ARM PrimeCell General Purpose Input/Output (PL061)
Simplified ARM PrimeCell GPIO (PL061) implementation. Only supports key 3 to
trigger a graceful shutdown of the AArch64 guest.
### ACPI device
This is a dedicated device for handling ACPI shutdown and reboot when ACPI is
@@ -75,12 +88,8 @@ feature is enabled by default.
## Virtio devices
For all virtio devices listed below, both `virtio-mmio` and `virtio-pci`
transport layers are supported, `virtio-pci` being the default.
Both `virtio-mmio` and `virtio-pci` can be compiled out. `virtio-pci` is
built-in by default, and enabled by default. If both transport layers were
built at the same time, `virtio-pci` would be the default transport layer.
For all virtio devices listed below, only `virtio-pci` transport layer is
supported.
### virtio-block

View File

@@ -52,14 +52,14 @@ Direct kernel boot option is preferred since we need to provide the custom kerne
Because _vhost-user_ expects a dedicated process (__virtiofsd__ in this case) to be able to access the guest RAM to communicate through the _virtqueues_ with the driver running in the guest, `--memory` option needs to be slightly modified. It needs to specify a backing file for the memory so that an external process can access it.
Assuming you have `clear-kvm.img` and `custom-vmlinux.bin` on your system, here is the __cloud-hypervisor__ command you need to run:
Assuming you have `focal-server-cloudimg-amd64.raw` and `custom-vmlinux.bin` on your system, here is the __cloud-hypervisor__ command you need to run:
```bash
./cloud-hypervisor \
--cpus 4 \
--memory "size=512,file=/dev/shm" \
--disk path=clear-kvm.img \
--memory "size=512M,shared=on" \
--disk path=focal-server-cloudimg-amd64.raw \
--kernel custom-vmlinux.bin \
--cmdline "console=ttyS0 reboot=k panic=1 nomodules root=/dev/vda3" \
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
--fs tag=myfs,socket=/tmp/virtiofs,num_queues=1,queue_size=512
```

35
docs/fuzzing.md Normal file
View File

@@ -0,0 +1,35 @@
# Fuzzing in Cloud Hypervisor
Cloud Hypervisor uses [cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz) for fuzzing individual components.
The fuzzers are are in the `fuzz/fuzz_targets` directory
## Preparation
Switch to nightly:
````
rustup override set nightly
````
Install `cargo fuzz`:
```
cargo install cargo-fuzz
```
## Running the fuzzers
e.g. To run the `qcow` fuzzer using all available CPUs:
```
cargo fuzz run qcow -j `nproc`
```
## Adding a new fuzzer
```
cargo fuzz add <new_fuzzer>
```
Inspiration for fuzzers can be found in [crosvm](https://chromium.googlesource.com/chromiumos/platform/crosvm/+/refs/heads/master/fuzz/)

View File

@@ -5,9 +5,7 @@ Currently Cloud Hypervisor only support hot plugging of CPU devices.
## 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`
or by using this kernel patch (available in 5.5rc1 and later): https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/patch/drivers/acpi/Makefile?id=ac36d37e943635fc072e9d4f47e40a48fbcdb3f0
This patch is integrated into the Clear Linux KVM and cloudguest images.
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
@@ -22,13 +20,14 @@ To use CPU hotplug start the VM with the number of max vCPUs greater than the nu
$ pushd $CLOUDH
$ sudo setcap cap_net_admin+ep ./cloud-hypervisor/target/release/cloud-hypervisor
$ ./cloud-hypervisor/target/release/cloud-hypervisor \
--kernel ./hypervisor-fw \
--disk path=clear-31890-kvm.img \
--kernel custom-vmlinux.bin \
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
--disk path=focal-server-cloudimg-amd64.raw \
--cpus boot=4,max=8 \
--memory size=1024M \
--net "tap=,mac=,ip=,mask=" \
--rng \
--api-socket=/tmp/ch-socket
--api-socket=/tmp/ch-socket
$ popd
```
@@ -37,7 +36,7 @@ Notice the addition of `--api-socket=/tmp/ch-socket` and a `max` parameter on `-
To ask the VMM to add additional vCPUs then use the resize API:
```shell
curl -H "Accept: application/json" -H "Content-Type: application/json" -i -XPUT --unix-socket /tmp/ch-socket -d "{ \"desired_vcpus\":8}" http://localhost/api/v1/vm.resize
./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:
@@ -57,31 +56,36 @@ 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
curl -H "Accept: application/json" -H "Content-Type: application/json" -i -XPUT --unix-socket /tmp/ch-socket -d "{ \"desired_vcpus\":2}" http://localhost/api/v1/vm.resize
./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.
## Memory Hot Plug
Extra memory can be added from a runing Cloud Hypervisor instance. This is controlled by two mechanisms:
### ACPI method
Extra memory can be added from a running Cloud Hypervisor instance. This is controlled by two mechanisms:
1. Allocating some of the guest physical address space for hotplug memory.
2. Making a HTTP API request to the VMM to ask for a new amount of RAM to be assigned to the VM. In the case of expanding the memory for the VM the new memory will be hotplugged into the running VM, if reducing the size of the memory then change will take effect after the next reboot.
To use memory hotplug start the VM specifying some size RAM in the "hotplug_size" parameter to the memory configuration. Not all the memory specified in this parameter will be available to hotplug as there are spacing and alignment requirements so it is recommended to make it larger than the hotplug RAM needed.
To use memory hotplug start the VM specifying some size RAM in the `hotplug_size` parameter to the memory configuration. Not all the memory specified in this parameter will be available to hotplug as there are spacing and alignment requirements so it is recommended to make it larger than the hotplug RAM needed.
Because the ACPI method is the default, there is no need to add the extra option `hotplug_method=acpi`.
```shell
$ pushd $CLOUDH
$ sudo setcap cap_net_admin+ep ./cloud-hypervisor/target/release/cloud-hypervisor
$ ./cloud-hypervisor/target/release/cloud-hypervisor \
--kernel ./hypervisor-fw \
--disk path=clear-31890-kvm.img \
--kernel custom-vmlinux.bin \
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
--disk path=focal-server-cloudimg-amd64.raw \
--cpus boot=4,max=8 \
--memory size=1024M,hotplug_size=8192M \
--net "tap=,mac=,ip=,mask=" \
--rng \
--api-socket=/tmp/ch-socket
--api-socket=/tmp/ch-socket
$ popd
```
@@ -91,10 +95,10 @@ Before issuing the API request it is necessary to run the following command insi
root@ch-guest ~ # echo online | sudo tee /sys/devices/system/memory/auto_online_blocks
```
To ask the VMM to add expand the RAM for the VM (request is in bytes):
To ask the VMM to expand the RAM for the VM:
```shell
curl -H "Accept: application/json" -H "Content-Type: application/json" -i -XPUT --unix-socket /tmp/ch-socket -d "{ \"desired_vcpus\": 4, \"desired_ram\" : 3221225472}" http://localhost/api/v1/vm.resize
./ch-remote --api-socket=/tmp/ch-socket resize --memory 3G
```
The new memory is now available to use inside the VM:
@@ -110,4 +114,135 @@ Due to guest OS limitations is is necessary to ensure that amount of memory adde
The same API can also be used to reduce the desired RAM for a VM but the change will not be applied until the VM is rebooted.
Memory and CPU resizing can be combined together into the same HTTP API request.
Memory and CPU resizing can be combined together into the same HTTP API request.
### virtio-mem method
Extra memory can be added and removed from a running Cloud Hypervisor instance. This is controlled by two mechanisms:
1. Allocating some of the guest physical address space for hotplug memory.
2. Making a HTTP API request to the VMM to ask for a new amount of RAM to be assigned to the VM.
To use memory hotplug start the VM specifying some size RAM in the `hotplug_size` parameter along with `hotplug_method=virtio-mem` to the memory configuration.
```shell
$ pushd $CLOUDH
$ sudo setcap cap_net_admin+ep ./cloud-hypervisor/target/release/cloud-hypervisor
$ ./cloud-hypervisor/target/release/cloud-hypervisor \
--kernel custom-vmlinux.bin \
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
--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
$ 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
```
The new memory is now available to use inside the VM:
```shell
free -h
total used free shared buff/cache available
Mem: 3.0Gi 71Mi 2.8Gi 0.0Ki 47Mi 2.8Gi
Swap: 32Mi 0B 32Mi
```
The same API can also be used to reduce the desired RAM for a VM. It is important to note that reducing RAM size might only partially work, as the guest might be using some of it.
## PCI Device Hot Plug
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.
To use PCI device hotplug start the VM with the HTTP server.
```shell
$ sudo setcap cap_net_admin+ep ./cloud-hypervisor/target/release/cloud-hypervisor
$ ./cloud-hypervisor/target/release/cloud-hypervisor \
--kernel custom-vmlinux.bin \
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
--disk path=focal-server-cloudimg-amd64.raw \
--cpus boot=4 \
--memory size=1024M \
--net "tap=,mac=,ip=,mask=" \
--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/
```
### Add Disk Device
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
```
### Add Fs Device
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
```
### Add Net Device
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
```
### Add Pmem Device
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
```
### Add Vsock Device
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
```
### Common Across All PCI Devices
The extra PCI device will be created and advertised to the running kernel. The new device can be found by checking the list of PCI devices.
```shell
root@ch-guest ~ # lspci
00:00.0 Host bridge: Intel Corporation Device 0d57
00:01.0 Unassigned class [ffff]: Red Hat, Inc. Virtio console (rev 01)
00:02.0 Mass storage controller: Red Hat, Inc. Virtio block device (rev 01)
00:03.0 Unassigned class [ffff]: Red Hat, Inc. Virtio RNG (rev 01)
```
After a reboot the added PCI device will remain.
### Remove PCI device
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
```
As per adding a PCI device to the guest, after a reboot the VM will be running without the removed PCI device.

55
docs/intel_sgx.md Normal file
View File

@@ -0,0 +1,55 @@
# Intel SGX
Intel® Software Guard Extensions (Intel® SGX) is an Intel technology designed
to increase the security of application code and data. Cloud-Hypervisor supports
SGX virtualization through KVM. Because SGX is built on hardware features that
cannot be emulated in software, virtualizing SGX requires support in KVM and in
the host kernel. The required Linux and KVM changes can be found in the
[KVM SGX Tree](https://github.com/intel/kvm-sgx).
Utilizing SGX in the guest requires a kernel/OS with SGX support, e.g. a kernel
built using the [SGX Linux Development Tree](https://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-sgx.git)
or the [KVM SGX Tree](https://github.com/intel/kvm-sgx). Running KVM SGX as the
guest kernel allows nested virtualization of SGX.
For more information about SGX, please refer to the [SGX Homepage](https://software.intel.com/sgx).
For more information about SGX SDK and how to test SGX, please refer to the
following [instructions](https://github.com/intel/linux-sgx).
## Cloud-Hypervisor support
Assuming the host exposes `/dev/sgx_virt_epc`, we can pass SGX enclaves through
the guest.
In order to use SGX enclaves within a Cloud-Hypervisor VM, we must define one
or several Enclave Page Cache (EPC) sections. Here is an example of a VM being
created with 2 EPC sections, the first one being 64MiB with pre-allocated
memory, the second one being 32MiB with no pre-allocated memory.
```bash
./cloud-hypervisor \
--cpus boot=1 \
--memory size=1G \
--disk path=focal-server-cloudimg-amd64.raw \
--kernel bzImage \
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
--sgx-epc size=64M,prefault=on size=32M,prefault=off
```
Once booted, and assuming your guest kernel contains the patches from the
[KVM SGX Tree](https://github.com/intel/kvm-sgx), you can validate SGX devices
have been correctly created under `/dev/sgx`:
```bash
ls /dev/sgx*
/dev/sgx_enclave /dev/sgx_provision /dev/sgx_virt_epc
```
From this point, it is possible to run any SGX application from the guest, as
it will access `/dev/sgx_enclave` device to create dedicated SGX enclaves.
Note: There is only one contiguous SGX EPC region, which contains all SGX EPC
sections. This region is exposed through ACPI and marked as reserved through
the e820 table. It is treated yet as another device, which means it should
appear at the end of the guest address space.

41
docs/io_throttling.md Normal file
View File

@@ -0,0 +1,41 @@
# I/O Throttling
Cloud Hypervisor now supports I/O throttling on virtio-block
devices. This support is based on the [`rate-limiter` module](https://github.com/firecracker-microvm/firecracker/tree/master/src/rate_limiter)
from Firecracker. This document explains the user interface of this
feature, and highlights some internal implementations that can help users
better understand the expected behavior of I/O throttling in practice.
Cloud Hypervisor allows to limit both the I/O bandwidth (e.g. bytes/s)
and I/O operations (ops/s) independently. To limit the I/O bandwidth, it
provides three user options, i.e., `bw_size` (bytes), `bw_one_time_burst`
(bytes), and `bw_refill_time` (ms). Both `bw_size` and `bw_refill_time`
are required, while `bw_one_time_burst` is optional.
Internally, these options define a TokenBucket with a maximum capacity
(`bw_size` bytes), an initial burst size (`bw_one_time_burst`) and an
interval for refilling purposes (`bw_refill_time`). The "refill-rate" is
`bw_size` bytes per `bw_refill_time` ms, and it is the constant rate at
which the tokens replenish. The refill process only starts happening
after the initial burst budget is consumed. Consumption from the token
bucket is unbounded in speed which allows for bursts bound in size by
the amount of tokens available. Once the token bucket is empty,
consumption speed is bound by the "refill-rate". Similarly, Cloud
Hypervisor provides another three options for limiting I/O operations,
i.e., `ops_size` (I/O operations), `bw_one_time_burst` (I/O operations),
and `bw_refill_time` (ms).
One caveat in the I/O throttling is that every-time the bucket gets
empty, it will stop I/O operations for a fixed amount of time
(`cool_down_time`). The `cool_down_time` now is fixed at `100 ms`, it
can have big implications to the actual rate limit (which can be a lot
different the expected "refill-rate" derived from user inputs). For
example, to have a 1000 IOPS limit, users should be able to provide
either of the following two options:
`ops_size=1000,ops_refill_time=1000` or
`ops_size=10,ops_refill_time=10`. However, the actual IOPS limits are
likely to be ~1000 IOPS and ~100 IOPS respectively. The reason is the
actual rate limit users get can be as low as
`ops_size/(ops_refill_time+cool_down_time)`. As a result, it is
generally advisable to keep `bw/ops_refill_time` larger than `100 ms`
(`cool_down_time`) to make sure the actual rate limit is close to users'
expectation ("refill-rate").

View File

@@ -86,11 +86,11 @@ virtual IOMMU:
```bash
./cloud-hypervisor \
--cpus 1 \
--cpus boot=1 \
--memory size=512M \
--disk path=clear-kvm.img,iommu=on \
--disk path=focal-server-cloudimg-amd64.raw,iommu=on \
--kernel custom-bzImage \
--cmdline "console=ttyS0 root=/dev/vda3" \
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
```
From a guest perspective, it is easy to verify if the device is protected by
@@ -163,11 +163,11 @@ be consumed.
```bash
./cloud-hypervisor \
--cpus 1 \
--memory size=8G,file=/dev/hugepages \
--disk path=clear-kvm.img \
--cpus boot=1 \
--memory size=8G,hugepages=on \
--disk path=focal-server-cloudimg-amd64.raw \
--kernel custom-bzImage \
--cmdline "console=ttyS0 root=/dev/vda3 hugepagesz=2M hugepages=2048" \
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw hugepagesz=2M hugepages=2048" \
--net tap=,mac=,iommu=on
```
@@ -180,11 +180,11 @@ passing through is `0000:00:01.0`.
```bash
./cloud-hypervisor \
--cpus 1 \
--memory size=8G,file=/dev/hugepages \
--disk path=clear-kvm.img \
--cpus boot=1 \
--memory size=8G,hugepages=on \
--disk path=focal-server-cloudimg-amd64.raw \
--kernel custom-bzImage \
--cmdline "console=ttyS0 root=/dev/vda3 kvm-intel.nested=1 vfio_iommu_type1.allow_unsafe_interrupts rw hugepagesz=2M hugepages=2048" \
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw kvm-intel.nested=1 vfio_iommu_type1.allow_unsafe_interrupts rw hugepagesz=2M hugepages=2048" \
--device path=/sys/bus/pci/devices/0000:00:01.0,iommu=on
```
@@ -200,10 +200,10 @@ Last thing is to start the L2 guest with the huge pages memory backend.
```bash
./cloud-hypervisor \
--cpus 1 \
--memory size=4G,file=/dev/hugepages \
--disk path=clear-kvm.img \
--cpus boot=1 \
--memory size=4G,hugepages=on \
--disk path=focal-server-cloudimg-amd64.raw \
--kernel custom-bzImage \
--cmdline "console=ttyS0 root=/dev/vda3" \
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
--device path=/sys/bus/pci/devices/0000:00:04.0
```

43
docs/logging.md Normal file
View File

@@ -0,0 +1,43 @@
# Logging
The target audience of this document is both:
* Developers who want to understand what log level to use and when,
* Users who want to debug issues with running their workloads in Cloud Hypervisor
## Control
The number of `-v` parameters passed to the `cloud-hypervisor` binary will determine the log level. Currenly the default is log messages up to `WARN:` (`warn!`) are included by default. The `--log-file` allows the log to be sent to a location other than `stderr`.
## Levels
### `error!()`
For immediate, unrecoverable errors where it does not make sense for the execution to continue as the behaviour of the VM is considerablely impacted.
Cloud Hypervisor should exit shortly after reporting this error (with a non-zero exit code). Generally this should be used during initial construction of the VM state before the virtual CPUs have begun running code.
A typical situation where this might occur is when the user is using command line options that conflict with each other or is trying to use a file that is not present on the filesystem.
Users should react to this error by checking their initial VM configuration.
### `warn!()`
A serious problem has occured but the execution of the VM can continue although some functionality might be impacted.
A typical example of where this level of message should be generated is during an API call request that cannot be fulfilled.
The user should investigate the meaning of this warning and take steps to ensure the correct functionality.
### `info!()`
Use `-v` to enable.
This level is for the benefit of developers. It should be used for sporadic and infrequent messages. The same message should not "spam" the logs. The VM should be usable when this level of debugging is enabled and trying to use `stdin/stdout` and the logs are going to `stderr`.
### `debug!()`
Use `-vv` 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`.

32
docs/macvtap-bridge.md Normal file
View File

@@ -0,0 +1,32 @@
# Using MACVTAP to Bridge onto Host Network
Cloud Hypervisor supports using a MACVTAP device which is derived from a MACVLAN. Full details of configuring MACVLAN or MACVTAP is out of scope of this document. However the example below indicates how to bridge the guest directly onto the the network the host is on. Due to the lack of hairpin mode it not usually possible to reach the guest directly from the host.
```bash
# The MAC address must be attached to the macvtap and be used inside the guest
mac="c2:67:4f:53:29:cb"
# Host network adapter to bridge the guest onto
host_net="eno1"
# Create the macvtap0 as a new virtual MAC associated with the host network
sudo ip link add link "$host_net" name macvtap0 type macvtap
sudo ip link set macvtap0 address "$mac" up
sudo ip link show macvtap0
# A new character device is created for this interface
tapindex=$(< /sys/class/net/macvtap0/ifindex)
tapdevice="/dev/tap$tapindex"
# Ensure that we can access this device
sudo chown "$UID.$UID" "$tapdevice"
# Use --net fd=3 to point to fd 3 which the shell has opened to point to the /dev/tapN device
target/debug/cloud-hypervisor \
--kernel ~/src/linux/vmlinux \
--disk path=~/workloads/focal.raw \
--cpus boot=1 --memory size=512M \
--cmdline "root=/dev/vda1 console=hvc0" \
--net fd=3,mac=$mac 3<>$"$tapdevice"
```
As the guest is now connected to the same L2 network as the host you can obtain an IP address based on your host network (potentially including via DHCP)

453
docs/memory.md Normal file
View File

@@ -0,0 +1,453 @@
# Memory
Cloud-Hypervisor has many ways to expose memory to the guest VM. This document
aims to explain what Cloud-Hypervisor is capable of and how it can be used to
meet the needs of very different use cases.
## Basic Parameters
`MemoryConfig` or what is known as `--memory` from the CLI perspective is the
easiest way to get started with Cloud-Hypervisor.
```rust
struct MemoryConfig {
size: u64,
mergeable: bool,
shared: bool,
hugepages: bool,
hugepage_size: Option<u64>,
hotplug_method: HotplugMethod,
hotplug_size: Option<u64>,
hotplugged_size: Option<u64>,
zones: Option<Vec<MemoryZoneConfig>>,
}
```
```
--memory <memory> Memory parameters "size=<guest_memory_size>,mergeable=on|off,shared=on|off,hugepages=on|off,hotplug_method=acpi|virtio-mem,hotplug_size=<hotpluggable_memory_size>,hotplugged_size=<hotplugged_memory_size>"
```
### `size`
Size of the RAM in the guest VM.
This option is mandatory when using the `--memory` parameter.
Value is an unsigned integer of 64 bits.
_Example_
```
--memory size=1G
```
### `mergeable`
Specifies if the pages from the guest RAM must be marked as _mergeable_. In
case this option is `true` or `on`, the pages will be marked with `madvise(2)`
to let the host kernel know which pages are eligible for being merged by the
KSM daemon.
This option can be used when trying to reach a higher density of VMs running
on a single host, as it will reduce the amount of memory consumed by each VM.
By default this option is turned off.
_Example_
```
--memory size=1G,mergeable=on
```
### `shared`
Specifies if the memory must be `mmap(2)` with `MAP_SHARED` flag.
By sharing a memory mapping, one can share the guest RAM with other processes
running on the host. One can use this option when running vhost-user devices
as part of the VM device model, as they will be driven by standalone daemons
needing access to the guest RAM content.
By default this option is turned off, which results in performing `mmap(2)`
with `MAP_PRIVATE` flag.
_Example_
```
--memory size=1G,shared=on
```
### `hugepages` and `hugepage_size`
Specifies if the memory must be created and `mmap(2)` with `MAP_HUGETLB` and size
flags. This performs a memory mapping relying on the specified huge page size. If no huge page size is supplied the system's default huge page size is used.
By using hugepages, one can improve the overall performance of the VM, assuming
the guest will allocate hugepages as well. Another interesting use case is VFIO
as it speeds up the VM's boot time since the amount of IOMMU mappings are
reduced.
The user is responsible for ensuring there are sufficient huge pages of the specified size for the VMM to use. Failure to do so may result in strange VMM behaviour.
By default this option is turned off.
_Example_
```
--memory size=1G,hugepages=on,hugepage_size=2M
```
### `hotplug_method`
Selects the way of adding and/or removing memory to/from a booted VM.
Possible values are `acpi` and `virtio-mem`. Default value is `acpi`.
_Example_
```
--memory size=1G,hotplug_method=acpi
```
### `hotplug_size`
Amount of memory that can be dynamically added to the VM.
Value is an unsigned integer of 64 bits. A value of 0 is invalid.
_Example_
```
--memory size=1G,hotplug_size=1G
```
### `hotplugged_size`
Amount of memory that will be dynamically added to the VM at boot. This option
allows for starting a VM with a certain amount of memory that can be reduced
during runtime.
This is only valid when the `hotplug_method` is `virtio-mem` as it does not
make sense for the `acpi` use case. When using ACPI, the memory can't be
resized after it has been extended.
This option is only valid when `hotplug_size` is specified, and its value can't
exceed the value of `hotplug_size`.
Value is an unsigned integer of 64 bits. A value of 0 is invalid.
_Example_
```
--memory size=1G,hotplug_method=virtio-mem,hotplug_size=1G,hotplugged_size=512M
```
## Advanced Parameters
`MemoryZoneConfig` or what is known as `--memory-zone` from the CLI perspective
is a power user parameter. It allows for a full description of the guest RAM,
describing how every memory region is backed and exposed to the guest.
```rust
struct MemoryZoneConfig {
id: String,
size: u64,
file: Option<PathBuf>,
shared: bool,
hugepages: bool,
host_numa_node: Option<u32>,
hotplug_size: Option<u64>,
hotplugged_size: Option<u64>,
}
```
```
--memory-zone <memory-zone> User defined memory zone parameters "size=<guest_memory_region_size>,file=<backing_file>,shared=on|off,hugepages=on|off,host_numa_node=<node_id>,id=<zone_identifier>,hotplug_size=<hotpluggable_memory_size>,hotplugged_size=<hotplugged_memory_size>"
```
This parameter expects one or more occurences, allowing for a list of memory
zones to be defined. It must be used with `--memory size=0`, clearly indicating
that the memory will be described through advanced parameters.
Each zone is given a list of options which we detail through the following
sections.
### `id`
Memory zone identifier. This identifier must be unique, otherwise an error will
be returned.
This option is useful when referring to a memory zone previously created. In
particular, the `--numa` parameter can associate a memory zone to a specific
NUMA node based on the memory zone identifier.
This option is mandatory when using the `--memory-zone` parameter.
Value is a string.
_Example_
```
--memory size=0
--memory-zone id=mem0,size=1G
```
### `size`
Size of the memory zone.
This option is mandatory when using the `--memory-zone` parameter.
Value is an unsigned integer of 64 bits.
_Example_
```
--memory size=0
--memory-zone id=mem0,size=1G
```
### `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.
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
if the provided path is a file, the snapshot operation will not perform any
copy of the guest RAM content for this specific memory zone since the user has
access to it and it would duplicate data already stored on the current
filesystem.
Value is a string.
_Example_
```
--memory size=0
--memory-zone id=mem0,size=1G,file=/foo/bar
```
### `shared`
Specifies if the memory zone must be `mmap(2)` with `MAP_SHARED` flag.
By sharing a memory zone mapping, one can share part of the guest RAM with
other processes running on the host. One can use this option when running
vhost-user devices as part of the VM device model, as they will be driven
by standalone daemons needing access to the guest RAM content.
By default this option is turned off, which result in performing `mmap(2)`
with `MAP_PRIVATE` flag.
_Example_
```
--memory size=0
--memory-zone id=mem0,size=1G,shared=on
```
### `hugepages`
Specifies if the memory zone must be `mmap(2)` with `MAP_HUGETLB` and
`MAP_HUGE_2MB` flags. This performs a memory zone mapping relying on 2MiB
pages instead of the default 4kiB pages.
By using hugepages, one can improve the overall performance of the VM, assuming
the guest will allocate hugepages as well. Another interesting use case is VFIO
as it speeds up the VM's boot time since the amount of IOMMU mappings are
reduced.
By default this option is turned off.
_Example_
```
--memory size=0
--memory-zone id=mem0,size=1G,hugepages=on
```
### `host_numa_node`
Node identifier of a node present on the host. This option will let the user
pick a specific NUMA node from which the memory must be allocated. After the
memory zone is `mmap(2)`, the NUMA policy for this memory mapping will be
applied through `mbind(2)`, relying on the provided node identifier. If the
node does not exist on the host, the call to `mbind(2)` will fail.
This option is useful when trying to back a VM memory with a specific type of
memory from the host. Assuming a host has two types of memory, with one slower
than the other, each related to a distinct NUMA node, one could create a VM
with slower memory accesses by backing the entire guest RAM from the furthest
NUMA node on the host.
This option also gives the opportunity to create a VM with non uniform memory
accesses as one could define a first memory zone backed by fast memory, and a
second memory zone backed by slow memory.
Value is an unsigned integer of 32 bits.
_Example_
```
--memory size=0
--memory-zone id=mem0,size=1G,host_numa_node=0
```
### `hotplug_size`
Amount of memory that can be dynamically added to the memory zone. Since
`virtio-mem` is the only way of resizing a memory zone, one must specify
the `hotplug_method=virtio-mem` to the `--memory` parameter.
Value is an unsigned integer of 64 bits. A value of 0 is invalid.
_Example_
```
--memory size=0,hotplug_method=virtio-mem
--memory-zone id=mem0,size=1G,hotplug_size=1G
```
### `hotplugged_size`
Amount of memory that will be dynamically added to a memory zone at VM's boot.
This option allows for starting a VM with a certain amount of memory that can
be reduced during runtime.
This is only valid when the `hotplug_method` is `virtio-mem` as it does not
make sense for the `acpi` use case. When using ACPI, the memory can't be
resized after it has been extended.
This option is only valid when `hotplug_size` is specified, and its value can't
exceed the value of `hotplug_size`.
Value is an unsigned integer of 64 bits. A value of 0 is invalid.
_Example_
```
--memory size=0,hotplug_method=virtio-mem
--memory-zone id=mem0,size=1G,hotplug_size=1G,hotplugged_size=512M
```
## NUMA settings
`NumaConfig` or what is known as `--numa` from the CLI perspective has been
introduced to define a guest NUMA topology. It allows for a fine description
about the CPUs and memory ranges associated with each NUMA node. Additionally
it allows for specifying the distance between each NUMA node.
```rust
struct NumaConfig {
id: u32,
cpus: Option<Vec<u8>>,
distances: Option<Vec<NumaDistance>>,
memory_zones: Option<Vec<String>>,
}
```
```
--numa <numa> Settings related to a given NUMA node "id=<node_id>,cpus=<cpus_id>,distances=<list_of_distances_to_destination_nodes>,memory_zones=<list_of_memory_zones>"
```
### `guest_numa_id`
Node identifier of a guest NUMA node. This identifier must be unique, otherwise
an error will be returned.
This option is mandatory when using the `--numa` parameter.
Value is an unsigned integer of 32 bits.
_Example_
```
--numa guest_numa_id=0
```
### `cpus`
List of virtual CPUs attached to the guest NUMA node identified by the
`guest_numa_id` option. This allows for describing a list of CPUs which
must be seen by the guest as belonging to the NUMA node `guest_numa_id`.
One can use this option for a fine grained description of the NUMA topology
regarding the CPUs associated with it, which might help the guest run more
efficiently.
Multiple values can be provided to define the list. Each value is an unsigned
integer of 8 bits.
For instance, if one needs to attach all CPUs from 0 to 4 to a specific node,
the syntax using `-` will help define a contiguous range with `cpus=0-4`. The
same example could also be described with `cpus=0:1:2:3:4`.
A combination of both `-` and `:` separators is useful when one might need to
describe a list containing all CPUs from 0 to 99 and the CPU 255, as it could
simply be described with `cpus=0-99:255`.
_Example_
```
--cpus boot=8
--numa guest_numa_id=0,cpus=1-3:7
--numa guest_numa_id=1,cpus=0:4-6
```
### `distances`
List of distances between the current NUMA node referred by `guest_numa_id`
and the destination NUMA nodes listed along with distances. This option let
the user choose the distances between guest NUMA nodes. This is important to
provide an accurate description of the way non uniform memory accesses will
perform in the guest.
One or more tuple of two values must be provided through this option. The first
value is an unsigned integer of 32 bits as it represents the destination NUMA
node. The second value is an unsigned integer of 8 bits as it represents the
distance between the current NUMA node and the destination NUMA node. The two
values are separated by `@` (`value1@value2`), meaning the destination NUMA
node `value1` is located at a distance of `value2`. Each tuple is separated
from the others with `:` separator.
For instance, if one wants to define 3 NUMA nodes, with each node located at
different distances, it can be described with the following example.
_Example_
```
--numa guest_numa_id=0,distances=1@15:2@25
--numa guest_numa_id=1,distances=0@15:2@20
--numa guest_numa_id=2,distances=0@25:1@20
```
### `memory_zones`
List of memory zones attached to the guest NUMA node identified by the
`guest_numa_id` option. This allows for describing a list of memory ranges
which must be seen by the guest as belonging to the NUMA node `guest_numa_id`.
This option can be very useful and powerful when combined with `host_numa_node`
option from `--memory-zone` parameter as it allows for creating a VM with non
uniform memory accesses, and let the guest know about it. It allows for
exposing memory zones through different NUMA nodes, which can help the guest
workload run more efficiently.
Multiple values can be provided to define the list. Each value is a string
referring to an existing memory zone identifier. Values are separated from
each other with the `:` separator.
_Example_
```
--memory size=0
--memory-zone id=mem0,size=1G
--memory-zone 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
```

View File

@@ -1,6 +1,6 @@
# How to use networking
cloud-hypervisor can emulate one or more virtual network interfaces, represented at the hypervisor host by [tap devices](https://www.kernel.org/doc/Documentation/networking/tuntap.txt). This guide briefly describes, in a manual and distribution neutral way, how to setup and use networking with cloud-hypevisor.
cloud-hypervisor can emulate one or more virtual network interfaces, represented at the hypervisor host by [tap devices](https://www.kernel.org/doc/Documentation/networking/tuntap.txt). This guide briefly describes, in a manual and distribution neutral way, how to setup and use networking with cloud-hypervisor.
## Multiple queue support for net devices ##
@@ -14,7 +14,7 @@ Note:
- Currently, it does not support to use ethtool to change the combined queue numbers in guest.
- Multiple queue is enabled for vhost-user-net backend in cloud-hypervisor, however, multiple thread is not added to handle mq, thus, the performance for vhost-user-net backend is not supposed to be improved. The multiple thread will be added for backend later.
- Performance test for vhost-user-net will be covered once vhost-user-net backend has mulitple thread supported.
- Performance test for vhost-user-net will be covered once vhost-user-net backend has multiple thread supported.
- Performance test for virtio-net is done by comparing 2 queue pairs with 1 queue pairs, that to run 2 iperf3 sessions in the same test environments, throughput is improved about 37%.
## Start cloud-hypervisor with net devices
@@ -25,9 +25,9 @@ Use one `--net` command-line argument from cloud-hypervisor to specify the emula
./cloud-hypervisor \
--cpus 4 \
--memory "size=512M" \
--disk path=my-root-disk.img \
--disk path=focal-server-cloudimg-amd64.raw \
--kernel my-vmlinux.bin \
--cmdline "console=ttyS0 reboot=k panic=1 nomodules root=/dev/vda3" \
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
--net tap=ich0,mac=a4:a1:c2:00:00:01,ip=192.168.4.2,mask=255.255.255.0,num_queues=2,queue_size=256 \
tap=ich1,mac=a4:a1:c2:00:00:02,ip=10.0.1.2,mask=255.255.255.0,num_queues=2,queue_size=256
```

45
docs/profiling.md Normal file
View File

@@ -0,0 +1,45 @@
# Profiling
`perf` can be used to profile the `cloud-hypervisor` binary but it is necessary to make some modifications to the the build in order to produce a binary that gives useful results.
## 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
```
## Profiling
`perf` may then be used in the usual manner:
e.g.
```
$ perf record -g target/release/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
```
For analysing the samples:
```
$ perf report -g
```
If profiling with a network device attached either the TAP device must be already created and configured or the profiling must be done as root so that the TAP device can be created.

68
docs/seccomp.md Normal file
View File

@@ -0,0 +1,68 @@
# Seccomp filtering
As a means to harden Cloud Hypervisor's security, the project leverages seccomp
filtering.
## What is seccomp filtering
A seccomp filter is a way for a process to tell the kernel which system calls
are authorized.
In case this process calls into a prohibited system call, the kernel will kill
the process right away.
## How does it apply to Cloud Hypervisor
Cloud Hypervisor is a multi threaded application. It spawns dedicated threads
for virtual CPUs, virtio devices and HTTP server, along with the main thread
representing the VMM.
Each of these threads has a limited scope of what it is expected to perform,
which is why different filters are applied to each of them.
By default, Cloud Hypervisor enables seccomp filtering as the project believes
that security should not be an option.
For development and debugging purposes, one might want to disable this feature
or log the faulty system call.
### Disabling seccomp filters
Append `--seccomp false` to Cloud Hypervisor's command line to prevent seccomp
filtering from being applied.
### Logging prohibited system calls
In the context of debug, one alternative to disabling seccomp filtering is to
log faulty system calls that would have caused the application to be killed by
the kernel.
Append `--seccomp log` to Cloud Hypervisor's command line to enable faulty
system calls to be logged.
The kernel running on the host machine must have the `audit` parameter enabled.
If this is not the case, update kernel boot options by appending `audit=1`.
Unauthorized system calls will be logged to the journal similarly to the
following example
```
type=SECCOMP msg=audit(1423263412.694:7878): auid=1000 uid=1000 gid=1000 ses=3 subj=unconfined_u:unconfined_r:cloud_hypervisor:s0-s0:c0.c1023 pid=1193 comm="cloud-hypervisor" exe="/usr/bin/cloud-hypervisor" sig=0 arch=c000003e syscall=47 compat=0 ip=0x7f4f63982604 code=0x50000
```
Provided `ausyscall` has been installed on the host, the system call can be
identified with
```
$ ausyscall 47
recvmsg
```
### Further debug with `strace`
One more way of debugging seccomp related issues is to use the `strace` tool as
it will log every system call issued by the process. It is important to use
`-f` option in order to trace each and every thread belonging to the process.
```
strace -f ./cloud-hypervisor ...
```

112
docs/snapshot_restore.md Normal file
View File

@@ -0,0 +1,112 @@
# Snapshot and Restore
The goal for the snapshot/restore feature is to provide the user with the
ability to take a snapshot of a previously paused virtual machine. This
snapshot can be used as the base for creating new identical virtual machines,
without the need to boot them from scratch. The restore codepath takes the
snapshot and creates the exact same virtual machine, restoring the previously
saved states. The new virtual machine is restored in a paused state, as it was
before the snapshot was performed.
This feature is important for the project as it establishes the first step
towards the support for live migration.
## Snapshot a Cloud-Hypervisor VM
First thing, we must run a Cloud-Hypervisor VM:
```bash
./cloud-hypervisor \
--api-socket /tmp/cloud-hypervisor.sock \
--cpus boot=4 \
--memory size=4G \
--kernel bzImage \
--cmdline "root=/dev/vda1 console=hvc0 rw" \
--disk path=focal-server-cloudimg-amd64.raw
```
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
```
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
```
Given the directory was present on the system, the snapshot will succeed and
it should contain the following files:
```bash
ll /home/foo/snapshot/
total 4194536
drwxrwxr-x 2 foo bar 4096 Jul 22 11:50 ./
drwxr-xr-x 47 foo bar 4096 Jul 22 11:47 ../
-rw------- 1 foo bar 3221225472 Jul 22 11:19 memory-region-0
-rw------- 1 foo bar 1073741824 Jul 22 11:19 memory-region-1
-rw------- 1 foo bar 217853 Jul 22 11:19 vm.json
```
In this particular example, we can observe that 2 memory region files were
created. That is explained by the size of the guest RAM, which is 4GiB in this
case. Because it exceeds 3GiB (which is where we can find a ~1GiB memory hole),
Cloud-Hypervisor needs 2 distinct memory regions to be created. Each memory
region's content is stored through a dedicated file, which explains why we end
up with 2 different files, the first one containing the guest RAM range 0-3GiB
and the second one containing the guest RAM range 3-4GiB.
`vm.json` gathers all information related to the virtual machine configuration
and state. The configuration bits are used to create a similar virtual machine
with the correct amount of CPUs, RAM, and other expected devices. The state
bits are used to restore each component in the state it was left before the
snapshot occurred.
## Restore a Cloud-Hypervisor VM
Given that one has access to an existing snapshot in `/home/foo/snapshot`,
it is possible to create a new VM based on this snapshot with the following
command:
```bash
./cloud-hypervisor \
--api-socket /tmp/cloud-hypervisor.sock \
--restore source_url=file:///home/foo/snapshot
```
Or using two different commands from two terminals:
```bash
# First terminal
./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
```
Remember the VM is restored in a `paused` state, which was the VM's state when
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
```
At this point, the VM is fully restored and is identical to the VM which was
snapshot earlier.
## Limitations
The support of snapshot/restore feature is still experimental, meaning one
might still find some bugs associated with it.
Additionally, some devices and features don't support to be snapshot and
restored yet:
- `vhost-user` devices
- `virtio-mem`
- Intel SGX
VFIO devices are out of scope.

75
docs/uefi.md Normal file
View File

@@ -0,0 +1,75 @@
# UEFI Boot
Cloud Hypervisor supports UEFI boot through the utilization of the EDK II based UEFI firmware.
## Building UEFI Firmware
To avoid any unnecessary issues, it is recommended to use Ubuntu 18.04 and its default toolset. Any other compatible Linux distribution is otherwise suitable, however it is suggested to use a temporary Docker container with Ubuntu 18.04 for a quick build on an existing Linux machine.
The commands below will compile an OVMF firmware suitable for Cloud Hypervisor.
```shell
sudo apt-get update
sudo apt-get install uuid-dev nasm iasl build-essential python3-distutils git
git clone https://github.com/cloud-hypervisor/edk2 -b ch
cd edk2
. edksetup.sh
git submodule update --init
echo "ACTIVE_PLATFORM=OvmfPkg/OvmfCh.dsc" >> Conf/target.txt
echo "TARGET_ARCH=X64" >> Conf/target.txt
echo "TOOL_CHAIN_TAG=GCC5" >> Conf/target.txt
make -C ./BaseTools
build
```
After the successful build, the resulting firmware binaries are available under `Build/OvmfCh/DEBUG_GCC5/FV` underneath the edk2 checkout.
## Using OVMF Binaries
Any UEFI capable image can be booted using the Cloud Hypervisor specific firmware. Windows guests under Cloud Hypervisor only support UEFI boot, therefore OVMF is mandatory there.
To make Cloud Hypervisor use UEFI boot, pass the `OVMF.fd` file path as an argument to the `--kernel` option. The firmware file will be opened in read only mode.
The same firmware can be used with Cloud Hypervisor or with QEMU. This is particularly useful if using QEMU for the preparation phase.
## Building UEFI Firmware with Compatibility Support Module (CSM)
CSM is a module that allows to boot legacy operating systems using the OVMF firmware. OVMF can embed a CSM build of SeaBIOS. To build the SeaBIOS with CSM support, add `CONFIG_CSM=y` to `.config` before the build. The outcome `out/Csm16.bin` is to be moved into `OvmfPkg/Csm/Csm16/Csm16.bin` before OVMF is built. Then, the OVMF build will have to be passed the `-D CSM_ENABLE` option in order to generate a legacy aware UEFI firmware. At the current stage, all the necessary patches are included in the Cloud Hypervisor specific [SeaBIOS branch](https://github.com/cloud-hypervisor/seabios/tree/ch). Taking into account the previous instructions, the modified command sequence to compile an OVMF binary with CSM support is the following one:
```shell
sudo apt-get update
sudo apt-get install uuid-dev nasm iasl build-essential python3-distutils git
git checkout https://github.com/cloud-hypervisor/seabios -b ch
cd seabios
make menuconfig
# Enable `CONFIG_CSM` and `CONFIG_QEMU_HARDWARE`
make CONFIG_CSM=y CONFIG_QEMU_HARDWARE=y
cd ..
git clone https://github.com/cloud-hypervisor/edk2 -b ch
cd edk2
. edksetup.sh
git submodule update --init
cp ../seabios/out/Csm16.bin OvmfPkg/Csm/Csm16/
echo "ACTIVE_PLATFORM=OvmfPkg/OvmfCh.dsc" >> Conf/target.txt
echo "TARGET_ARCH=X64" >> Conf/target.txt
echo "TOOL_CHAIN_TAG=GCC5" >> Conf/target.txt
make -C ./BaseTools
build
```
Please note, that the CSM support has currently only been tested with Linux guests. There are no plans to provide legacy support for other OSes (e.g. Windows).
# Links
- [OVMF wiki](https://github.com/tianocore/tianocore.github.io/wiki/OVMF)
- [Cloud Hypervisor specific tree](https://github.com/cloud-hypervisor/edk2/tree/ch)
- [Redhat OVMF Status Report](https://access.redhat.com/sites/default/files/attachments/ovmf-whtepaper-031815.pdf)
- [SeaBIOS Build Overview](https://www.seabios.org/Build_overview#Build_as_a_UEFI_Compatibility_Support_Module_.28CSM.29)

View File

@@ -66,10 +66,10 @@ takes the device's sysfs path as an argument. In our example it is
```
./target/debug/cloud-hypervisor \
--kernel ~/vmlinux \
--disk path=~/clear-29160-kvm.img \
--disk path=~/focal-server-cloudimg-amd64.raw \
--console off \
--serial tty \
--cmdline "console=ttyS0 reboot=k panic=1 nomodules i8042.noaux i8042.nomux i8042.nopnp i8042.dumbkbd root=/dev/vda3" \
--cmdline "console=ttyS0 root=/dev/vda1 rw" \
--cpus 4 \
--memory size=512M \
--device path=/sys/bus/pci/devices/0000:01:00.0/
@@ -78,5 +78,3 @@ takes the device's sysfs path as an argument. In our example it is
The guest kernel will then detect the card reader on its PCI bus and provided
that support for this device is enabled, it will probe and enable it for the
guest to use.

View File

@@ -73,10 +73,10 @@ VMs run in client mode. They connect to the socket created by the `dpdkvhostuser
# From the test terminal. We need to create one vhost-user-blk device for the --disk.
./cloud-hypervisor \
--cpus boot=4 \
--memory size=1024M,file=/dev/hugepages \
--memory size=1024M,hugepages=on,shared=true \
--kernel linux/arch/x86/boot/compressed/vmlinux.bin \
--cmdline "console=ttyS0 reboot=k panic=1 nomodules i8042.noaux i8042.nomux i8042.nopnp i8042.dumbkbd root=/dev/vda3 iommu=off" \
--disk "path=images/clear-kvm.img" "num_queues=4,queue_size=128,vhost_user=true,socket=/var/tmp/vhost.1" \
--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 \
--console off \
--serial tty \
--rng
@@ -88,11 +88,11 @@ login in guest
# Use lsblk command to find out vhost-user-blk device
lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 253:0 0 8.5G 0 disk
├─vda1 253:1 0 511M 0 part
├─vda2 253:2 0 32M 0 part [SWAP]
└─vda3 253:3 0 8G 0 part /
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 252:0 0 2.2G 0 disk
├─vda1 252:1 0 2.1G 0 part /
├─vda14 252:14 0 4M 0 part
└─vda15 252:15 0 106M 0 part /boot/efi
vdb 253:16 0 512M 0 disk
The vhost-user-blk device is /dev/vdb

View File

@@ -76,19 +76,19 @@ VMs run in client mode. They connect to the socket created by the `dpdkvhostuser
# From one terminal. We need to give the cloud-hypervisor binary the NET_ADMIN capabilities for it to set TAP interfaces up on the host.
./cloud-hypervisor \
--cpus boot=2 \
--memory size=512M,file=/dev/hugepages \
--memory size=512M,hugepages=on,shared=true \
--kernel vmlinux \
--cmdline "reboot=k panic=1 nomodules i8042.noaux i8042.nomux i8042.nopnp i8042.dumbkbd root=/dev/vda3" \
--disk path=clear-kvm.img \
--net "mac=52:54:00:02:d9:01,vhost_user=true,socket=/var/run/openvswitch/vhost-user1,num_queues=4"
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
--disk path=focal-server-cloudimg-amd64.raw \
--net mac=52:54:00:02:d9:01,vhost_user=true,socket=/var/run/openvswitch/vhost-user1,num_queues=4
# From another terminal. We need to give the cloud-hypervisor binary the NET_ADMIN capabilities for it to set TAP interfaces up on the host.
./cloud-hypervisor \
--cpus boot=2 \
--memory size=512M,file=/dev/hugepages \
--memory size=512M,hugepages=on,shared=true \
--kernel vmlinux \
--cmdline "reboot=k panic=1 nomodules i8042.noaux i8042.nomux i8042.nopnp i8042.dumbkbd root=/dev/vda3" \
--disk path=clear-kvm.img \
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
--disk path=focal-server-cloudimg-amd64.raw \
--net "mac=52:54:20:11:C5:02,vhost_user=true,socket=/var/run/openvswitch/vhost-user2,num_queues=4"
```

92
docs/virtiofs-root.md Normal file
View File

@@ -0,0 +1,92 @@
# HOWTO VirtioFS rootfs
A quick guide for using virtiofs as a cloud-hypervisor guest's rootfs (i.e.
with no root block device). This document is a quick getting started guide.
There are many more steps to take to make this a production ready, secure
setup.
## Prerequisites
1. virtiofsd from the qemu project
* We are using the Qemu version for now
* There is a Rust version being worked on that may be a better option in the future
* Part of the qemu-system-common package on Ubuntu
* Part of the qemu-common package on Fedora
2. cloud-hypervisor - the newer the better, but I tested with 0.12
3. a rootfs - This howto uses an alpine rootfs available here:
* https://dl-cdn.alpinelinux.org/alpine/v3.13/releases/x86_64/alpine-minirootfs-3.13.2-x86_64.tar.gz
* Others should work
## To create the VM rootfs
```bash
mkdir rootfs/
cd rootfs
# this needs sudo to be able to set root permissions on fs components
sudo tar -xf /path/to/alpine-minirootfs-3.13.1-x86_64.tar.gz
# this will get created when the VM actually boots by the dhcp client
# but we need it in the chroot to download packages
sudo cp /etc/resolv.conf etc/
# the alpine mini rootfs is meant for docker containers, we need a few extra
# things for a working rootfs
sudo chroot $PWD apk add openrc busybox-initscripts
# we are using the paravirt console in cloud-hypervisor, so enable it in init
# append it after the other console since it doesn't work just appending it
sudo sed -i '/vt100/a \n# paravirt console\nhvc0::respawn:/sbin/getty -L hvc0 115200 vt100' etc/inittab
# set no password for root user... you obviously don't want to do this for
# any sort of production setup
sudo sed -i 's/root:!::0:::::/root:::0:::::/' etc/shadow
# set up init scripts
for i in acpid crond
sudo ln -sf /etc/init.d/$i etc/runlevels/default/$i
end
for i in bootmisc hostname hwclock loadkmap modules networking swap sysctl syslog urandom
sudo ln -sf /etc/init.d/$i etc/runlevels/boot/$i
end
for i in killprocs mount-ro savecache
sudo ln -sf /etc/init.d/$i etc/runlevels/shutdown/$i
end
for i in devfs dmesg hwdrivers mdev
sudo ln -sf /etc/init.d/$i etc/runlevels/sysinit/$i
end
# setup network config
echo 'auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
' | sudo tee etc/network/interfaces
```
## To run the VM
```bash
# starting in the directory above rootfs
sudo virtiofsd --socket-path=$PWD/virtiofs-rootfs.sock -o source=$PWD/rootfs -o cache=none &
sudo cloud-hypervisor \
--cpus boot=1,max=1 \
--kernel vmlinux \
--fs tag=/dev/root,socket=$PWD/virtiofs-rootfs.sock \
--memory size=2G,shared=on \
--cmdline "console=hvc0 rootfstype=virtiofs root=/dev/root ro debug" \
--api-socket $PWD/ch.sock \
--rng \
--net ...
```
Note: an important part of the above is the `tag=/dev/root` and
`root=/dev/root` parts. For whatever reason, it would only work with that as
the tag.
Note: another important bit is that the memory is shared. This is required for
virtiofs
## Message from the author
If you find any issues or have suggestions, feel free to reach out to @iggy on
the cloud-hypervisor slack. Also if this works for you, I'd like to know as
well. It would also be nice to get steps for preparing other distribution root
filesystems.

337
docs/windows.md Normal file
View File

@@ -0,0 +1,337 @@
# Windows Support
Starting with the release version [0.10.0](https://github.com/cloud-hypervisor/cloud-hypervisor/releases/tag/v0.10.0), Cloud Hypervisor supports Windows guests.
__Requirements__
- Host with KVM enabled
- [UEFI](uefi.md) capable Windows guest image with Virtio drivers integrated
Any modern Windows Server version is compatible. Cloud Hypervisor has been successfully tested with Windows Server 2019 and Windows Server Core 2004.
At the current stage, only UEFI capable Windows images are supported. This implies the presence of the OVMF firmware during the Windows installation and in any subsequent usage. BIOS boot is not supported.
The subsequent sections will tell, in detail, how to prepare an appropriate Windows image.
## Image Preparation
### Installation using the stock Windows ISO
__Prerequisites__
- QEMU, version >=5.0.0 is recommended.
- Windows installation ISO. Obtained through MSDN, Visual Studio subscription, evaluation center, etc.
- [VirtIO driver ISO](https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/)
- Suitable [OVMF](uefi.md) firmware
- With the suggested image size of 30G, there should be enough free disk space to hold the installation ISO and any other necessary files
This step currently requires QEMU to install Windows onto the guest. QEMU is only used at the preparation stage, the resulting image is then fully functional with Cloud Hypervisor.
Preparing several command parts as these will be used in the follow up sections as well.
```shell
IMG_FILE=windows-disk.qcow
WIN_ISO_FILE=en_windows_server_version_2004_updated_may_2020_x64_dvd_1e7f1cfa.iso
VIRTIO_ISO_FILE=virtio-win-0.1.185.iso
OVMF_DIR=./FV
```
Create an empty image file, `qcow` or `raw` is supported.
```shell
qemu-img create -f qcow2 $IMG_FILE 30G
```
Begin the Windows installation process under QEMU
```shell
qemu-system-x86_64 \
-machine q35,accel=kvm \
-cpu host \
-m 4G \
-bios ./$OVMF_DIR/OVMF_CODE.fd \
-cdrom ./$WIN_ISO_FILE \
-drive file=./$VIRTIO_ISO_FILE,index=0,media=cdrom
-drive if=none,id=root,file=./$IMG_FILE \
-device virtio-blk-pci,drive=root,disable-legacy=on \
-device virtio-net-pci,netdev=mynet0,disable-legacy=on \
-netdev user,id=mynet0 \
-vga std
```
Before the installation can proceed, point the Windows installation program to the VirtIO disk and install the necessary storage controller drivers. After that, the attached hard drive will become visible and the actual installation can commence.
After the installation has completed, proceed further to the configuration section. QEMU will be needed at least once more to enable the Windows Special Administration Console (SAC) and to possibly install extra device drivers.
## Image Usage
The basic command to boot a Windows image. The configuration section should be checked before executing it for the first time.
```shell
cloud-hypervisor \
--kernel ./$OVMF_DIR/OVMF.fd \
--disk path=./$IMG_FILE \
--cpus boot=1,kvm_hyperv=on \
--memory size=4G \
--serial tty \
--console off \
--net tap=
```
It is necessary to always:
- Carry the OVMF firmware in the `--kernel` option
- Add `kvm_hyperv=on` to the `--cpus` option
In cases where the host processor supports address space > 39 bits, it might be necessary to limit the address space. It can be done by appending the option `max_phys_bits=X` to the `--cpus` parameter, where `X` is the number of bits to be supported. Windows was tested to support at least 39-bit address space.
To daemonize the Cloud Hypervisor process, `nohup` can be used. Some STDIO redirections might need to be done. In a simple case it is sufficient to just redirect all the output to `/dev/null`.
## Image Configuration
### Device Drivers
After the Windows installation has finished under QEMU, there might be still devices with no drivers installed. This might happen for example, when a device was not used during the installation. In particular it is important to ensure that the VirtIO network device is setup correctly because further steps for the configuration and the usage require network in most case.
Boot once more under QEMU and use the [Device Manager](https://support.microsoft.com/en-in/help/4028443/windows-10-update-drivers), to ensure all the device drivers, and especially the network card, are installed correctly. Also, as Cloud Hypervisor can introduce new devices, it is advisable to repeat the procedure while booted under Cloud Hypervisor, when the RDP access to the image is functional.
### Windows Special Administration Console (SAC) enablement
SAC provides a text based console access to the Windows guest. As Cloud Hypervisor doesn't implement a VGA adaptor, SAC is an important instrument for the Windows guest management.
Boot the Windows image under QEMU and execute the below commands to permanently enable SAC
```cmd
bcdedit /emssettings emsport:1 emsbaudrate:115200
bcdedit /ems on
bcdedit /bootems on
```
Once SAC is enabled, the image can be booted under Cloud Hypervisor. The SAC prompt will show up
<pre>
Computer is booting, SAC started and initialized.
Use the "ch -?" command for information about using channels.
Use the "?" command for general help.
SAC>
</pre>
To open a console on the guest, the command sequence below can be used
<pre>
SAC>cmd
The Command Prompt session was successfully launched.
SAC>
EVENT: A new channel has been created. Use "ch -?" for channel help.
Channel: Cmd0001
SAC>ch -si 1
</pre>
See also the [links](#Links) section for a more extended SAC documentation.
## Network
This section illustrates the Windows specific corner points for the VM network configuration. For the extended networking guide, including bridging for multiple VMs, follow [networking.md](networking.md).
### Basic Networking
As the simplest option, using `--net tap=` in the Cloud Hypervisor command line will create a `vmtapX` device on the host with the default IPv4 adress `192.168.249.1`. After SAC becomes available, the guest configuration can be set with
<pre>
SAC>i 10 192.168.249.2 255.255.255.0 192.168.249.1
</pre>
Where `10` is the device index as shown by the `i` command.
### Guest Internet Connectivity
Additional steps are necessary to provide the guest with internet access.
- On the guest, add the DNS server either by using `netsh` or by opening `Network and Connectivity Center` and editing the adapter properties.
- On the host, configure the traffic forwarding. Replace the `NET_DEV` with the name of your network device.
```shell
NET_DEV=wlp3s0
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o $NET_DEV -j MASQUERADE
```
### Remote Desktop Protocol (RDP) enablement
#### Using QEMU
- Execute `SystemPropertiesRemote`
- In the properties window, choose "Allow remote connections to this computer"
- Click "Select Users" and add some user to the allow list
#### Using powershell
```powershell
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\" -Name "fDenyTSConnections" -Value 0
Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
Add-LocalGroupMember -Group "Remote Desktop Users" -Member someuser
```
Administrators can always RDP, non administrator users have to be explicitly enabled.
Once the configuration is set, RDP clients can connect to `192.168.249.2`.
### SSH
#### Enable using powershell
```powershell
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Start-Service sshd
Set-Service -Name sshd -StartupType Automatic
```
This allows for SSH login from a remote machine, for example through the `administrator` user: `ssh administrator@192.168.249.2`. For a more detailed OpenSSH guide, please follow the MSDN article from the [links](#links) section.
## Debugging
The Windows guest debugging process relies heavily on QEMU and [socat](http://www.dest-unreach.org/socat/). The procedure requires two Windows VMs:
- A debugger VM running under QEMU.
- A debuggee, a Windows VM that has been created in the previous steps, running under Cloud Hypervisor or QEMU.
The connection between both guests happens over TCP, whereby on the guest side it is automatically translated to a COM port. Because the VMs are connected through TCP, the debugging infrastructure can be distributed over the network. The serial port, while slowly transferring data, is common enough to support a wide range of cases and tools.
In this excercise, [WinDbg](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/) is used. Any other debugger of choice with the ability to use serial connection can be used instead.
### Debugger and Debuggee
#### WinDbg VM
For simplicity, the debugger VM is supposed to be only running under QEMU. It will require VGA and doesn't neccessarily depend on UEFI. As an OS, it can carry any supported Windows OS where the debugger of choice can be installed. The simplest way is to follow the image preparation instructions from the previous chapter, but avoid using the OVMF firmware. It is also not required to use VirtIO drivers, whereby it might be useful in some case. Though, while creating the image file for the debugger VM, be sure to choose a sufficient disk size that counts in the need to save the corresponding debug symbols and sources.
To create the debugger Windows VM, the following command can be used:
```shell
qemu-system-x86_64 \
-machine q35,accel=kvm \
-cpu host \
-smp 1 \
-m 4G \
-cdrom ./$WIN_ISO_FILE \
-drive file=./$VIRTIO_ISO_FILE,index=0,media=cdrom
-drive if=none,id=root,file=./windbg-disk.qcow \
-device virtio-blk-pci,drive=root,disable-legacy=on \
-device virtio-net-pci,netdev=mynet0,disable-legacy=on \
-netdev user,id=mynet0,net=192.168.178.0/24,host=192.168.178.1,dhcpstart=192.168.178.64,hostname=windbg-host \
-vga std
```
A non server Windows OS like Windows 10 can be used to carry the debugging tools in the debugger VM.
#### Debuggee VM
The debuggee VM is the one that we've learned to configure and run in the first section. There might be various reasons to debug. For example, there could be an issue in the Windows guest with an emulated device or an included driver. Or, we might want to develop a custom feature like a kernel driver to be available in the guest.
Note, that there are several ways to debug Windows, not all of them need to be enabled at the same time. For example, if developing a kernel module, the only useful options would be to configure for the serial debugging and enable the kernel debug. In that case, any crash or misbehavior in the boot loader or kernel would be ignored. The commands below must be run as administrator on the debuggee guest VM.
##### Turn On Serial Debugging
This will configure the debugging to be enabled and instruct to use the serial port for it.
```cmd
bcdedit /dbgsettings serial debugport:1 baudrate:115200
```
##### Turn On Kernel Debuging
```cmd
bcdedit /debug on
```
##### Turn On Boot Loader Debug
```cmd
bcdedit /bootdebug on
```
##### Turn on boot manager debug
```cmd
bcdedit /set {bootmgr} bootdebug on
```
##### Disable Recovery Screen On Boot Failure
There could be a situation, where a crash is debugged. In such cases, the guest could be left in an inconsistent state. The default Windows behavior would be to boot into the recovery screen, however in some cases it might be not desired. To make Windows ignore failures and always proceed to booting the OS, use the command below:
```cmd
bcdedit /set {default} bootstatuspolicy ignoreallfailures
```
### Debugging Process
#### Invoke the WinDbg VM
```shell
qemu-system-x86_64 \
-machine q35,accel=kvm \
-cpu host \
-smp 1 \
-m 4G \
-drive if=none,id=root,file=./windbg-disk.qcow \
-device virtio-blk-pci,drive=root,disable-legacy=on \
-serial tcp::4445,server,nowait \
-device virtio-net-pci,netdev=mynet0,disable-legacy=on \
-netdev user,id=mynet0,net=192.168.178.0/24,host=192.168.178.1,dhcpstart=192.168.178.64,hostname=windbg-host \
-vga std
```
Note, this VM has the networking enabled. It is needed, because symbols and sources might need to be fetched from a network location.
Also, notice the `-serial` parameter - that's what does the magic on exposing the serial port to the guest while connecting the debugger VM with a client VM through the network. SAC/EMS needs to be disabled in the debugger VM, as otherwise the COM device might be blocked.
Hereafter, WinDbg can be started using a command below:
```cmd
set _NT_DEBUG_PORT=com1
set _NT_DEBUG_BAUD_RATE=115200
windbg -v -d -k
```
Once started, WinDbg will wait for an incoming connection which is going to be initialized by the debuggee VM started in the next section.
#### Invoke the Debuggee VM
##### Under QEMU
Essentially it would be the command like depicted in the guest preparation sections, with a few modifications:
```shell
qemu-system-x86_64 \
-machine q35,accel=kvm \
-cpu host \
-m 4G \
-bios ./$OVMF_DIR/OVMF_CODE.fd \
-cdrom ./$WIN_ISO_FILE \
-drive file=./$VIRTIO_ISO_FILE,index=0,media=cdrom
-drive if=none,id=root,file=./$IMG_FILE \
-device virtio-blk-pci,drive=root,disable-legacy=on \
-device virtio-net-pci,netdev=mynet0,disable-legacy=on \
-netdev user,id=mynet0 \
-serial tcp:127.0.0.1:4445 \
-vga std
```
It is to see, that `-serial` parameter is used here, to establish the connection with the debugger VM.
To disable HPET, attach `--no-hpet`. To enable hypervisor reference timer, use `-cpu host,hv-time`. These and other options can be used to achieve better [Hyper-V compatibility](https://archive.fosdem.org/2019/schedule/event/vai_enlightening_kvm/attachments/slides/2860/export/events/attachments/vai_enlightening_kvm/slides/2860/vkuznets_fosdem2019_enlightening_kvm.pdf).
##### Cloud Hypervisor
The `socat` tool is used to establish the QEMU compatible behavior. Here as well, the Cloud Hypervisor command used to run the Windows guest is to be used. Put the command into a shell script:
`socat SYSTEM:"./ch-script",openpty,raw,echo=0 TCP:localhost:4445`
The reason to pack the command into the shell script is that the command might contain a comma. When using SYSTEM, the shell command can't contain `,` or `!!`.
## Links
- [Fedora VirtIO guide for Windows](https://docs.fedoraproject.org/en-US/quick-docs/creating-windows-virtual-machines-using-virtio-drivers/)
- [VirtIO driver binaries](https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/)
- [VirtIO driver sources](https://github.com/virtio-win/kvm-guest-drivers-windows)
- [Emergency Management Services](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc787940(v=ws.10))
- [OpenSSH server/client configuration](https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse)
- [Windows guest debugging under KVM](https://www.linux-kvm.org/page/WindowsGuestDrivers/GuestDebugging)
- ["ENLIGHTENING" KVM](https://archive.fosdem.org/2019/schedule/event/vai_enlightening_kvm/attachments/slides/2860/export/events/attachments/vai_enlightening_kvm/slides/2860/vkuznets_fosdem2019_enlightening_kvm.pdf)

11
event_monitor/Cargo.toml Normal file
View File

@@ -0,0 +1,11 @@
[package]
name = "event_monitor"
version = "0.1.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2018"
[dependencies]
libc = "0.2.91"
serde = {version = ">=1.0.27", features = ["rc"] }
serde_derive = ">=1.0.27"
serde_json = ">=1.0.9"

77
event_monitor/src/lib.rs Normal file
View File

@@ -0,0 +1,77 @@
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
#[macro_use]
extern crate serde_derive;
use std::borrow::Cow;
use std::collections::HashMap;
use std::fs::File;
use std::os::unix::io::AsRawFd;
use std::time::{Duration, Instant};
static mut MONITOR: Option<(File, Instant)> = None;
/// This function must only be called once from the main process before any threads
/// are created to avoid race conditions
pub fn set_monitor(file: File) -> Result<(), std::io::Error> {
assert!(unsafe { MONITOR.is_none() });
let fd = file.as_raw_fd();
let ret = unsafe {
let mut flags = libc::fcntl(fd, libc::F_GETFL);
flags |= libc::O_NONBLOCK;
libc::fcntl(fd, libc::F_SETFL, flags)
};
if ret < 0 {
return Err(std::io::Error::last_os_error());
}
unsafe {
MONITOR = Some((file, Instant::now()));
};
Ok(())
}
#[derive(Serialize)]
struct Event<'a> {
timestamp: Duration,
source: &'a str,
event: &'a str,
properties: Option<&'a HashMap<Cow<'a, str>, Cow<'a, str>>>,
}
pub fn event_log(source: &str, event: &str, properties: Option<&HashMap<Cow<str>, Cow<str>>>) {
if let Some((file, start)) = unsafe { MONITOR.as_ref() } {
let e = Event {
timestamp: start.elapsed(),
source,
event,
properties,
};
serde_json::to_writer_pretty(file, &e).ok();
}
}
/*
Through the use of Cow<'a, str> it is possible to use String as well as
&str as the parameters:
e.g.
event!("cpu_manager", "create_vcpu", "id", cpu_id.to_string());
*/
#[macro_export]
macro_rules! event {
($source:expr, $event:expr) => {
$crate::event_log($source, $event, None)
};
($source:expr, $event:expr, $($key:expr, $value:expr),*) => {
{
let mut properties = ::std::collections::HashMap::new();
$(
properties.insert($key.into(), $value.into());
)+
$crate::event_log($source, $event, Some(&properties))
}
};
}

4
fuzz/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
target
corpus
artifacts

765
fuzz/Cargo.lock generated Normal file
View File

@@ -0,0 +1,765 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "acpi_tables"
version = "0.1.0"
dependencies = [
"vm-memory",
]
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [
"winapi",
]
[[package]]
name = "anyhow"
version = "1.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cddc5f91628367664cc7c69714ff08deee8a3efc54623011c772544d7b2767"
[[package]]
name = "api_client"
version = "0.1.0"
[[package]]
name = "arbitrary"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "698b65a961a9d730fb45b6b0327e20207810c9f61ee421b082b27ba003f49e2b"
[[package]]
name = "arc-swap"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4d7d63395147b81a9e570bcc6243aaf71c017bd666d4909cfef0085bdda8d73"
[[package]]
name = "arch"
version = "0.1.0"
dependencies = [
"acpi_tables",
"anyhow",
"arch_gen",
"byteorder",
"hypervisor",
"libc",
"linux-loader",
"log",
"serde",
"serde_derive",
"serde_json",
"thiserror",
"vm-memory",
"vm-migration",
]
[[package]]
name = "arch_gen"
version = "0.1.0"
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "block_util"
version = "0.1.0"
dependencies = [
"io-uring",
"libc",
"log",
"qcow",
"serde",
"serde_derive",
"serde_json",
"thiserror",
"virtio-bindings",
"vm-memory",
"vm-virtio",
"vmm-sys-util",
]
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "2.33.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"term_size",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "cloud-hypervisor"
version = "0.13.0"
dependencies = [
"anyhow",
"api_client",
"clap",
"epoll",
"event_monitor",
"hypervisor",
"libc",
"log",
"option_parser",
"seccomp",
"serde_json",
"signal-hook",
"thiserror",
"vm-memory",
"vmm",
"vmm-sys-util",
]
[[package]]
name = "cloud-hypervisor-fuzz"
version = "0.0.0"
dependencies = [
"block_util",
"cloud-hypervisor",
"libc",
"libfuzzer-sys",
"qcow",
"seccomp",
"virtio-devices",
"vm-memory",
"vm-virtio",
"vmm-sys-util",
]
[[package]]
name = "devices"
version = "0.1.0"
dependencies = [
"acpi_tables",
"anyhow",
"bitflags",
"byteorder",
"epoll",
"libc",
"log",
"serde",
"serde_derive",
"serde_json",
"vm-device",
"vm-memory",
"vm-migration",
"vmm-sys-util",
]
[[package]]
name = "epoll"
version = "4.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20df693c700404f7e19d4d6fae6b15215d2913c27955d2b9d6f2c0f537511cd0"
dependencies = [
"bitflags",
"libc",
]
[[package]]
name = "event_monitor"
version = "0.1.0"
dependencies = [
"libc",
"serde",
"serde_derive",
"serde_json",
]
[[package]]
name = "hermit-abi"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
dependencies = [
"libc",
]
[[package]]
name = "hypervisor"
version = "0.1.0"
dependencies = [
"anyhow",
"epoll",
"iced-x86",
"kvm-bindings",
"kvm-ioctls",
"libc",
"log",
"serde",
"serde_derive",
"serde_json",
"thiserror",
"vm-memory",
"vmm-sys-util",
]
[[package]]
name = "iced-x86"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4261b15a556aa9b83b976b7aa4613f5a3b80351683af14c5d8d7e62c00869d5a"
dependencies = [
"lazy_static",
"static_assertions",
]
[[package]]
name = "io-uring"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb82832e05cc4ca298f198a8db108837b4f7b7b1248e3cba8e48f151aece80cf"
dependencies = [
"bitflags",
"libc",
]
[[package]]
name = "itoa"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
[[package]]
name = "kvm-bindings"
version = "0.4.0"
source = "git+https://github.com/cloud-hypervisor/kvm-bindings?branch=ch-v0.4.0#1a68725639283e622f4bb64584885b30bfe8be44"
dependencies = [
"serde",
"serde_derive",
"vmm-sys-util",
]
[[package]]
name = "kvm-ioctls"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74058b16912c6723db02d4ca3ec919b73cd41512ccd3b6202cf91ae8d6c9dce5"
dependencies = [
"kvm-bindings",
"libc",
"vmm-sys-util",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
[[package]]
name = "libfuzzer-sys"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86c975d637bc2a2f99440932b731491fc34c7f785d239e38af3addd3c2fd0e46"
dependencies = [
"arbitrary",
"cc",
]
[[package]]
name = "linux-loader"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c819cc8275b0f2c1ed9feec455ca288b45d82932384a6a5f7a86812ee3427459"
dependencies = [
"vm-memory",
]
[[package]]
name = "log"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
[[package]]
name = "micro_http"
version = "0.1.0"
source = "git+https://github.com/firecracker-microvm/micro-http?branch=master#59ab64440a95f7b16253fef67b5201c2ec4adaf7"
dependencies = [
"epoll",
]
[[package]]
name = "net_gen"
version = "0.1.0"
dependencies = [
"vmm-sys-util",
]
[[package]]
name = "net_util"
version = "0.1.0"
dependencies = [
"epoll",
"libc",
"log",
"net_gen",
"serde",
"virtio-bindings",
"vm-memory",
"vm-virtio",
"vmm-sys-util",
]
[[package]]
name = "option_parser"
version = "0.1.0"
[[package]]
name = "pci"
version = "0.1.0"
dependencies = [
"anyhow",
"byteorder",
"hypervisor",
"libc",
"log",
"serde",
"serde_derive",
"serde_json",
"vfio-bindings",
"vfio-ioctls",
"vm-allocator",
"vm-device",
"vm-memory",
"vm-migration",
"vmm-sys-util",
]
[[package]]
name = "proc-macro2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [
"unicode-xid",
]
[[package]]
name = "qcow"
version = "0.1.0"
dependencies = [
"byteorder",
"libc",
"log",
"remain",
"vmm-sys-util",
]
[[package]]
name = "quote"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "remain"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ba1e78fa68412cb93ef642fd4d20b9a941be49ee9333875ebaf13112673ea7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "seccomp"
version = "0.1.0"
source = "git+https://github.com/firecracker-microvm/firecracker?tag=v0.22.0#cc5387637c132e500b4857b80b5a239d8d732b77"
dependencies = [
"libc",
]
[[package]]
name = "serde"
version = "1.0.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
[[package]]
name = "serde_derive"
version = "1.0.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "signal-hook"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6aa894ef3fade0ee7243422f4fbbd6c2b48e6de767e621d37ef65f2310f53cea"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-registry"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6"
dependencies = [
"libc",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "syn"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "term_size"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"term_size",
"unicode-width",
]
[[package]]
name = "thiserror"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "vfio-bindings"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a21f546f2bda37f5a8cfb138c87f95b8e34d2d78d6a7a92ba3785f4e08604a7"
dependencies = [
"vmm-sys-util",
]
[[package]]
name = "vfio-ioctls"
version = "0.1.0"
source = "git+https://github.com/rust-vmm/vfio-ioctls?branch=master#a87b13bdec026e8144b91f30f35451a966d8c1ca"
dependencies = [
"byteorder",
"kvm-bindings",
"kvm-ioctls",
"log",
"vfio-bindings",
"vm-memory",
"vmm-sys-util",
]
[[package]]
name = "vhost"
version = "0.1.0"
source = "git+https://github.com/rust-vmm/vhost?branch=master#ee3e8722706c984b3dfe12d3a130e92101b78e8f"
dependencies = [
"bitflags",
"libc",
"vmm-sys-util",
]
[[package]]
name = "virtio-bindings"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ff512178285488516ed85f15b5d0113a7cdb89e9e8a760b269ae4f02b84bd6b"
[[package]]
name = "virtio-devices"
version = "0.1.0"
dependencies = [
"anyhow",
"arc-swap",
"block_util",
"byteorder",
"epoll",
"event_monitor",
"io-uring",
"libc",
"log",
"net_gen",
"net_util",
"pci",
"seccomp",
"serde",
"serde_derive",
"serde_json",
"vhost",
"virtio-bindings",
"vm-allocator",
"vm-device",
"vm-memory",
"vm-migration",
"vm-virtio",
"vmm-sys-util",
]
[[package]]
name = "vm-allocator"
version = "0.1.0"
dependencies = [
"arch",
"libc",
"vm-memory",
]
[[package]]
name = "vm-device"
version = "0.1.0"
dependencies = [
"anyhow",
"serde",
"serde_derive",
"serde_json",
"thiserror",
"vfio-ioctls",
"vm-memory",
"vmm-sys-util",
]
[[package]]
name = "vm-memory"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "625f401b1b8b3ac3d43f53903cd138cfe840bd985f8581e553027b31d2bb8ae8"
dependencies = [
"arc-swap",
"libc",
"winapi",
]
[[package]]
name = "vm-migration"
version = "0.1.0"
dependencies = [
"anyhow",
"serde",
"serde_derive",
"serde_json",
"thiserror",
"vm-memory",
]
[[package]]
name = "vm-virtio"
version = "0.1.0"
dependencies = [
"log",
"serde",
"serde_derive",
"serde_json",
"virtio-bindings",
"vm-memory",
]
[[package]]
name = "vmm"
version = "0.1.0"
dependencies = [
"acpi_tables",
"anyhow",
"arc-swap",
"arch",
"bitflags",
"block_util",
"clap",
"devices",
"epoll",
"event_monitor",
"hypervisor",
"lazy_static",
"libc",
"linux-loader",
"log",
"micro_http",
"net_util",
"option_parser",
"pci",
"qcow",
"seccomp",
"serde",
"serde_derive",
"serde_json",
"signal-hook",
"thiserror",
"vfio-ioctls",
"virtio-devices",
"vm-allocator",
"vm-device",
"vm-memory",
"vm-migration",
"vm-virtio",
"vmm-sys-util",
]
[[package]]
name = "vmm-sys-util"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01cf11afbc4ebc0d5c7a7748a77d19e2042677fc15faa2f4ccccb27c18a60605"
dependencies = [
"bitflags",
"libc",
"serde",
"serde_derive",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

42
fuzz/Cargo.toml Normal file
View File

@@ -0,0 +1,42 @@
[package]
name = "cloud-hypervisor-fuzz"
version = "0.0.0"
authors = ["Automatically generated"]
publish = false
edition = "2018"
[package.metadata]
cargo-fuzz = true
[dependencies]
block_util = { path = "../block_util" }
libc = "0.2.90"
libfuzzer-sys = "0.4"
qcow = { path = "../qcow" }
seccomp = { git = "https://github.com/firecracker-microvm/firecracker", tag = "v0.22.0" }
virtio-devices = { path = "../virtio-devices" }
vmm-sys-util = "0.8.0"
vm-virtio = { path = "../vm-virtio" }
vm-memory = "0.5.0"
[patch.crates-io]
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.4.0", features = ["with-serde", "fam-wrappers"] }
[dependencies.cloud-hypervisor]
path = ".."
# Prevent this from interfering with workspaces
[workspace]
members = ["."]
[[bin]]
name = "qcow"
path = "fuzz_targets/qcow.rs"
test = false
doc = false
[[bin]]
name = "block"
path = "fuzz_targets/block.rs"
test = false
doc = false

140
fuzz/fuzz_targets/block.rs Normal file
View File

@@ -0,0 +1,140 @@
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#![no_main]
use block_util::{async_io::DiskFile, qcow_sync::QcowDiskSync};
use libfuzzer_sys::fuzz_target;
use seccomp::SeccompAction;
use std::ffi;
use std::fs::File;
use std::io::{self, Cursor, Read, Seek, SeekFrom};
use std::mem::size_of;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::path::PathBuf;
use std::sync::Arc;
use virtio_devices::{Block, VirtioDevice, VirtioInterrupt, VirtioInterruptType};
use vm_memory::{Bytes, GuestAddress, GuestMemoryAtomic, GuestMemoryMmap};
use vm_virtio::Queue;
use vmm_sys_util::eventfd::EventFd;
const MEM_SIZE: u64 = 256 * 1024 * 1024;
const DESC_SIZE: u64 = 16; // Bytes in one virtio descriptor.
const QUEUE_SIZE: u16 = 16; // Max entries in the queue.
const CMD_SIZE: usize = 16; // Bytes in the command.
fuzz_target!(|bytes| {
let size_u64 = size_of::<u64>();
let mem = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE as usize)]).unwrap();
// The fuzz data is interpreted as:
// starting index 8 bytes
// command location 8 bytes
// command 16 bytes
// descriptors circular buffer 16 bytes * 3
if bytes.len() < 4 * size_u64 {
// Need an index to start.
return;
}
let mut data_image = Cursor::new(bytes);
let first_index = read_u64(&mut data_image);
if first_index > MEM_SIZE / DESC_SIZE {
return;
}
let first_offset = first_index * DESC_SIZE;
if first_offset as usize + size_u64 > bytes.len() {
return;
}
let command_addr = read_u64(&mut data_image);
if command_addr > MEM_SIZE - CMD_SIZE as u64 {
return;
}
if mem
.write_slice(
&bytes[2 * size_u64..(2 * size_u64) + CMD_SIZE],
GuestAddress(command_addr as u64),
)
.is_err()
{
return;
}
data_image.seek(SeekFrom::Start(first_offset)).unwrap();
let desc_table = read_u64(&mut data_image);
if mem
.write_slice(&bytes[32..], GuestAddress(desc_table as u64))
.is_err()
{
return;
}
let mut q = Queue::new(QUEUE_SIZE);
q.ready = true;
q.size = QUEUE_SIZE / 2;
q.max_size = QUEUE_SIZE;
let queue_evts: Vec<EventFd> = vec![EventFd::new(0).unwrap()];
let queue_fd = queue_evts[0].as_raw_fd();
let queue_evt = unsafe { EventFd::from_raw_fd(libc::dup(queue_fd)) };
let shm = memfd_create(&ffi::CString::new("fuzz").unwrap(), 0).unwrap();
let disk_file: File = unsafe { File::from_raw_fd(shm) };
let qcow_disk = Box::new(QcowDiskSync::new(disk_file, false)) as Box<dyn DiskFile>;
let mut block = Block::new(
"tmp".to_owned(),
qcow_disk,
PathBuf::from(""),
false,
false,
2,
256,
SeccompAction::Allow,
None,
)
.unwrap();
block
.activate(
GuestMemoryAtomic::new(mem),
Arc::new(NoopVirtioInterrupt {}),
vec![q],
queue_evts,
)
.ok();
queue_evt.write(77).unwrap(); // Rings the doorbell, any byte will do.
});
fn read_u64<T: Read>(readable: &mut T) -> u64 {
let mut buf = [0u8; size_of::<u64>()];
readable.read_exact(&mut buf[..]).unwrap();
u64::from_le_bytes(buf)
}
fn memfd_create(name: &ffi::CStr, flags: u32) -> Result<RawFd, io::Error> {
let res = unsafe { libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags) };
if res < 0 {
Err(io::Error::last_os_error())
} else {
Ok(res as RawFd)
}
}
pub struct NoopVirtioInterrupt {}
impl VirtioInterrupt for NoopVirtioInterrupt {
fn trigger(
&self,
_int_type: &VirtioInterruptType,
_queue: Option<&Queue>,
) -> std::result::Result<(), std::io::Error> {
Ok(())
}
}

49
fuzz/fuzz_targets/qcow.rs Normal file
View File

@@ -0,0 +1,49 @@
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
#![no_main]
use libfuzzer_sys::fuzz_target;
use qcow::{QcowFile, RawFile};
use std::ffi;
use std::fs::File;
use std::io::{self, Cursor, Read, Seek, SeekFrom, Write};
use std::mem::size_of;
use std::os::unix::io::{FromRawFd, RawFd};
// Take the first 64 bits of data as an address and the next 64 bits as data to
// store there. The rest of the data is used as a qcow image.
fuzz_target!(|bytes| {
if bytes.len() < 16 {
// Need an address and data, each are 8 bytes.
return;
}
let mut disk_image = Cursor::new(bytes);
let addr = read_u64(&mut disk_image);
let value = read_u64(&mut disk_image);
let shm = memfd_create(&ffi::CString::new("fuzz").unwrap(), 0).unwrap();
let mut disk_file: File = unsafe { File::from_raw_fd(shm) };
disk_file.write_all(&bytes[16..]).unwrap();
disk_file.seek(SeekFrom::Start(0)).unwrap();
if let Ok(mut qcow) = QcowFile::from(RawFile::new(disk_file, false)) {
if qcow.seek(SeekFrom::Start(addr)).is_ok() {
let _ = qcow.write_all(&value.to_le_bytes());
}
}
});
fn read_u64<T: Read>(readable: &mut T) -> u64 {
let mut buf = [0u8; size_of::<u64>()];
readable.read_exact(&mut buf[..]).unwrap();
u64::from_le_bytes(buf)
}
fn memfd_create(name: &ffi::CStr, flags: u32) -> Result<RawFd, io::Error> {
let res = unsafe { libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags) };
if res < 0 {
Err(io::Error::last_os_error())
} else {
Ok(res as RawFd)
}
}

35
hypervisor/Cargo.toml Normal file
View File

@@ -0,0 +1,35 @@
[package]
name = "hypervisor"
version = "0.1.0"
authors = ["Microsoft Authors"]
edition = "2018"
license = "Apache-2.0 OR BSD-3-Clause"
[features]
kvm = ["kvm-ioctls", "kvm-bindings"]
mshv = ["mshv-ioctls", "mshv-bindings"]
tdx = []
[dependencies]
anyhow = "1.0"
epoll = ">=4.0.1"
thiserror = "1.0"
libc = "0.2.91"
log = "0.4.14"
kvm-ioctls = { version = "0.8.0", optional = true }
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.4.0", features = ["with-serde", "fam-wrappers"], optional = true }
mshv-bindings = {git = "https://github.com/cloud-hypervisor/mshv", branch = "master", features = ["with-serde", "fam-wrappers"], optional = true }
mshv-ioctls = { git = "https://github.com/cloud-hypervisor/mshv", branch = "master", optional = true}
serde = {version = ">=1.0.27", features = ["rc"] }
serde_derive = ">=1.0.27"
serde_json = ">=1.0.9"
vm-memory = { version = "0.5.0", features = ["backend-mmap", "backend-atomic"] }
vmm-sys-util = { version = ">=0.5.0", features = ["with-serde"] }
[target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86]
version = "1.11"
default-features = false
features = ["std", "decoder", "op_code_info", "instr_info", "fast_fmt"]
[dev-dependencies]
env_logger = "0.8.3"

View File

@@ -0,0 +1,148 @@
//
// Copyright © 2020 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
extern crate thiserror;
use core::fmt::Debug;
use std::fmt::{self, Display};
use thiserror::Error;
#[derive(Clone, Copy, Error, Debug)]
pub struct Exception<T: Debug> {
vector: T,
ip: u64,
error: Option<u32>,
payload: Option<u64>,
}
impl<T: Debug> Display for Exception<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Exception {:?} at IP {:#x}", self.vector, self.ip)
}
}
#[derive(Error, Debug)]
pub enum PlatformError {
#[error("Invalid address: {0}")]
InvalidAddress(#[source] anyhow::Error),
#[error("Invalid register: {0}")]
InvalidRegister(#[source] anyhow::Error),
#[error("Invalid state: {0}")]
InvalidState(#[source] anyhow::Error),
#[error("Memory read failure: {0}")]
MemoryReadFailure(#[source] anyhow::Error),
#[error("Memory write failure: {0}")]
MemoryWriteFailure(#[source] anyhow::Error),
#[error("Get CPU state failure: {0}")]
GetCpuStateFailure(#[source] anyhow::Error),
#[error("Set CPU state failure: {0}")]
SetCpuStateFailure(#[source] anyhow::Error),
#[error("Translate virtual address: {0}")]
TranslateVirtualAddress(#[source] anyhow::Error),
#[error("Unsupported CPU Mode: {0}")]
UnsupportedCpuMode(#[source] anyhow::Error),
#[error("Invalid instruction operand: {0}")]
InvalidOperand(#[source] anyhow::Error),
}
#[derive(Error, Debug)]
pub enum EmulationError<T: Debug> {
#[error("Unsupported instruction: {0}")]
UnsupportedInstruction(#[source] anyhow::Error),
#[error("Unsupported memory size: {0}")]
UnsupportedMemorySize(#[source] anyhow::Error),
#[error("Invalid operand: {0}")]
InvalidOperand(#[source] anyhow::Error),
#[error("Wrong number of operands: {0}")]
WrongNumberOperands(#[source] anyhow::Error),
#[error("Instruction Exception: {0}")]
InstructionException(Exception<T>),
#[error("Instruction fetching error: {0}")]
InstructionFetchingError(#[source] anyhow::Error),
#[error("Platform emulation error: {0}")]
PlatformEmulationError(PlatformError),
#[error(transparent)]
EmulationError(#[from] anyhow::Error),
}
/// The PlatformEmulator trait emulates a guest platform.
/// It's mostly a guest resources (memory and CPU state) getter and setter.
///
/// A CpuState is an architecture specific type, representing a CPU state.
/// The emulator and its instruction handlers modify a given CPU state and
/// eventually ask the platform to commit it back through `set_cpu_state`.
pub trait PlatformEmulator: Send + Sync {
type CpuState: Clone;
/// Read guest memory into a u8 slice.
///
/// # Arguments
///
/// * `gva` - Guest virtual address to read from.
/// * `data` - Data slice to read into.
///
fn read_memory(&self, gva: u64, data: &mut [u8]) -> Result<(), PlatformError>;
/// Write a u8 slice into guest memory.
///
/// # Arguments
///
/// * `gva` - Guest virtual address to write into.
/// * `data` - Data slice to be written.
///
fn write_memory(&mut self, gva: u64, data: &[u8]) -> Result<(), PlatformError>;
/// Get a CPU state from the guest.
///
/// # Arguments
///
/// * `cpu_id` - Logical CPU ID.
///
fn cpu_state(&self, cpu_id: usize) -> Result<Self::CpuState, PlatformError>;
/// Set a guest CPU state.
///
/// # Arguments
///
/// * `cpu_id` - Logical CPU ID.
/// * `state` - State to set the CPU into.
///
fn set_cpu_state(&self, cpu_id: usize, state: Self::CpuState) -> Result<(), PlatformError>;
/// Translate a guest virtual address into a physical one
///
/// # Arguments
///
/// * `gva` - Guest virtual address to translate.
///
fn gva_to_gpa(&self, gva: u64) -> Result<u64, PlatformError>;
/// Fetch instruction bytes from memory.
///
/// # Arguments
///
/// * `ip` - Instruction pointer virtual address to start fetching instructions from.
///
fn fetch(&self, ip: u64, instruction_bytes: &mut [u8]) -> Result<(), PlatformError>;
}
pub type EmulationResult<S, E> = std::result::Result<S, EmulationError<E>>;

View File

@@ -0,0 +1,18 @@
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
//
// Copyright © 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
//
// Copyright © 2020, Microsoft Corporation
//
pub mod emulator;
#[cfg(target_arch = "x86_64")]
#[macro_use]
pub mod x86;

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