!43 [sync] PR-41: Update version to 2.1.0-1

From: @openeuler-sync-bot 
Reviewed-by: @imxcc 
Signed-off-by: @imxcc
This commit is contained in:
openeuler-ci-bot 2022-02-12 09:14:31 +00:00 committed by Gitee
commit aa8acc19a6
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
20 changed files with 14 additions and 3566 deletions

View File

@ -1,227 +0,0 @@
From aeede83c9a6a4b07aee477b67d763561a3f342e6 Mon Sep 17 00:00:00 2001
From: Ming Yang <yangming73@huawei.com>
Date: Wed, 18 Aug 2021 18:44:39 +0800
Subject: [PATCH 01/10] docs: fix some statement
Signed-off-by: Ming Yang <yangming73@huawei.com>
---
docs/config_guidebook.md | 32 ++++++++++++++++---------------
docs/interconnect_with_libvirt.md | 8 ++++----
docs/stratovirt_aarch64.xml | 10 +++++-----
docs/stratovirt_x86.xml | 12 ++++++------
4 files changed, 32 insertions(+), 30 deletions(-)
diff --git a/docs/config_guidebook.md b/docs/config_guidebook.md
index 72b4c7e..e1279e1 100644
--- a/docs/config_guidebook.md
+++ b/docs/config_guidebook.md
@@ -148,7 +148,7 @@ There is only one argument for iothread:
Virtio block device is a virtual block device, which process read and write requests in virtio queue from guest.
-Eight properties are supported for virtio block device.
+Nine properties are supported for virtio block device.
* drive_id: unique device-id in StratoVirt.
* path_on_host: the path of block device in host.
@@ -156,7 +156,8 @@ Eight properties are supported for virtio block device.
* read_only: whether virtio block device is read-only. If not set, default is false.
* direct: open block device with `O_DIRECT` mode. If not set, default is true.
* iothread: indicate which iothread will be used, if not specified the main thread will be used. (optional)
-* iops: used to limit IO operations for block device. (optional)
+* throttling.iops-total: used to limit IO operations for block device. (optional)
+* if: drive type, for block drive, it should be `none`. If not set, default is `none` (optional)
* format: the format of block image, default value `raw`. NB: currently only `raw` is supported. (optional)
If not set, default is raw.
@@ -170,11 +171,11 @@ If you want to boot VM with a virtio block device as rootfs, you should add `roo
```shell
# virtio mmio block device.
--drive id=drive_id,file=path_on_host[,serial=serial_num,readonly=off,direct=off]
--device virtio-blk-device,drive=drive_id[,iothread=iothread1,iops=200]
+-drive id=drive_id,file=path_on_host[,serial=serial_num,readonly=off,direct=off,throttling.iops-total=200]
+-device virtio-blk-device,drive=drive_id[,iothread=iothread1]
# virtio pci block device.
--drive id=drive_id,file=path_on_host[,serial=serial_num,readonly=off,direct=off]
--device virtio-blk-pci,drive=drive_id,bus=pcie.0,addr=0x3.0x0[,iothread=iothread1,iops=200]
+-drive id=drive_id,file=path_on_host[,serial=serial_num,readonly=off,direct=off,throttling.iops-total=200]
+-device virtio-blk-pci,drive=drive_id,bus=pcie.0,addr=0x3.0x0[,iothread=iothread1]
```
@@ -207,11 +208,11 @@ is a single function device, the function number should be set to zero.
```shell
# virtio mmio net device
--netdev tap,id=netdevid,ifname=host_dev_name[,mac=12:34:56:78:9A:BC]
--device virtio-net-device,netdev=netdevid,id=netid[,iothread=iothread1]
+-netdev tap,id=netdevid,ifname=host_dev_name
+-device virtio-net-device,netdev=netdevid,id=netid[,iothread=iothread1,mac=12:34:56:78:9A:BC]
# virtio pci net device
--netdev tap,id=netdevid,ifname=host_dev_name[,mac=12:34:56:78:9A:BC]
--device virtio-net-pci,netdev=netdevid,id=netid,bus=pcie.0,addr=0x2.0x0[,iothread=iothread1]
+-netdev tap,id=netdevid,ifname=host_dev_name
+-device virtio-net-pci,netdev=netdevid,id=netid,bus=pcie.0,addr=0x2.0x0[,iothread=iothread1,mac=12:34:56:78:9A:BC]
```
StratoVirt also supports vhost-net to get a higher performance in network. It can be set by
@@ -222,11 +223,11 @@ given when `vhost=on`, StratoVirt gets it by opening "/dev/vhost-net" automatica
```shell
# virtio mmio net device
--netdev tap,id=netdevid,ifname=host_dev_name,vhost=on[,mac=12:34:56:78:9A:BC,vhostfd=2]
--device virtio-net-device,netdev=netdevid,id=netid[,iothread=iothread1]
+-netdev tap,id=netdevid,ifname=host_dev_name,vhost=on[,vhostfd=2]
+-device virtio-net-device,netdev=netdevid,id=netid[,iothread=iothread1,mac=12:34:56:78:9A:BC]
# virtio pci net device
--netdev tap,id=netdevid,ifname=host_dev_name,vhost=on[,mac=12:34:56:78:9A:BC,vhostfd=2]
--device virtio-net-pci,netdev=netdevid,id=netid,bus=pcie.0,addr=0x2.0x0[,iothread=iothread1]
+-netdev tap,id=netdevid,ifname=host_dev_name,vhost=on[,vhostfd=2]
+-device virtio-net-pci,netdev=netdevid,id=netid,bus=pcie.0,addr=0x2.0x0[,iothread=iothread1,mac=12:34:56:78:9A:BC]
```
*How to set a tap device?*
@@ -290,10 +291,11 @@ If you want use it, need:
And `modprobe vhost_vsock` in the host.
-Two properties can be set for virtio vsock device.
+Three properties can be set for virtio vsock device.
* vsock_id: unique device-id in StratoVirt.
* guest_cid: a unique Context-ID in host to each guest, it should satisfy `3<=guest_cid<u32:MAX`.
+* vhostfd: fd of vsock device. (optional).
For vhost-vsock-pci, two more properties are required.
* bus: name of bus which to attach.
diff --git a/docs/interconnect_with_libvirt.md b/docs/interconnect_with_libvirt.md
index d5205ed..2dee64b 100644
--- a/docs/interconnect_with_libvirt.md
+++ b/docs/interconnect_with_libvirt.md
@@ -34,7 +34,7 @@ Optional value of `arch` are: `aarch64` and `x86_64`. On X86 platform, supported
`/path/to/standard_vm_kernel` is the path of standard vm kernel.
```
<kernel>/path/to/standard_vm_kernel</kernel>
-<cmdline>console=ttys0 root=/dev/vda reboot=k panic=1 rw</cmdline>
+<cmdline>console=ttyS0 root=/dev/vda reboot=k panic=1 rw</cmdline>
```
- feature:
@@ -77,7 +77,7 @@ Pflash can be added by the following config.
`/path/to/pflash` is the path of pflash file.
```
<loader readonly='yes' type='pflash'>/path/to/pflash</loader>
-<nvram template='/path/to/OVMF_VARS'/>/path/to/OVMF_VARS</nvram>
+<nvram template='/path/to/OVMF_VARS'>/path/to/OVMF_VARS</nvram>
```
- iothread
@@ -144,7 +144,7 @@ To use `virsh console` command, the virtio console with redirect `pty` should be
<controller type='pci' index='5' model='pcie-root-port' />
<rng model='virtio'>
<rate period='1000' bytes='1234'/>
- <backend model='random'>/dev/random</backend>
+ <backend model='random'>/path/to/random_file</backend>
<address type='pci' domain='0x000' bus='0x05' slot='0x00' function='0x00'/>
</rng>
```
@@ -153,7 +153,7 @@ To use `virsh console` command, the virtio console with redirect `pty` should be
```
<controller type='pci' index='7' model='pcie-root-port' />
-<hostdev model='subsystem' type='pci' managed='yes'>
+<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
diff --git a/docs/stratovirt_aarch64.xml b/docs/stratovirt_aarch64.xml
index 9bbf8d2..fa37d2b 100644
--- a/docs/stratovirt_aarch64.xml
+++ b/docs/stratovirt_aarch64.xml
@@ -13,7 +13,7 @@
<os>
<type arch='aarch64' machine='virt'>hvm</type>
<kernel>/path/to/standard_vm_kernel</kernel>
- <cmdline>console=ttys0 root=/dev/vda reboot=k panic=1 rw</cmdline>
+ <cmdline>console=ttyAMA0 root=/dev/vda reboot=k panic=1 rw</cmdline>
<loader readonly='yes' type='pflash'>/path/to/pflash</loader>
</os>
<features>
@@ -24,8 +24,8 @@
<emulator>/path/to/StratoVirt_binary_file</emulator>
<controller type='pci' index='0' model='pcie-root'/>
<!-- block -->
- <disk type='file' device='disk' iothread='1'>
- <driver name='qemu' type='raw'/>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='raw' iothread='1'/>
<source file='/path/to/rootfs'/>
<target dev='hda' bus='virtio'/>
<address type='pci' domain='0x000' bus='0x00' slot='0x01' function='0x00'/>
@@ -58,7 +58,7 @@
<!-- rng -->
<rng model='virtio'>
<rate period='1000' bytes='1234'/>
- <backend model='random'>/dev/random</backend>
+ <backend model='random'>/path/to/random_file</backend>
<address type='pci' domain='0x000' bus='0x00' slot='0x05' function='0x00'/>
</rng>
<!-- vsock -->
@@ -67,7 +67,7 @@
<address type='pci' domain='0x000' bus='0x00' slot='0x06' function='0x00'/>
</vsock>
<!-- vfio -->
- <hostdev model='subsystem' type='pci' managed='yes'>
+ <hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
diff --git a/docs/stratovirt_x86.xml b/docs/stratovirt_x86.xml
index b561a5f..68069c0 100644
--- a/docs/stratovirt_x86.xml
+++ b/docs/stratovirt_x86.xml
@@ -13,9 +13,9 @@
<os>
<type arch='x86_64' machine='q35'>hvm</type>
<kernel>/path/to/standard_vm_kernel</kernel>
- <cmdline>console=ttys0 root=/dev/vda reboot=k panic=1 rw</cmdline>
+ <cmdline>console=hvc0 root=/dev/vda reboot=k panic=1 rw</cmdline>
<loader readonly='yes' type='pflash'>/path/to/pflash</loader>
- <nvram template='/path/to/OVMF_VARS'/>/path/to/OVMF_VARS</nvram>
+ <nvram template='/path/to/OVMF_VARS'>/path/to/OVMF_VARS</nvram>
</os>
<features>
<acpi/>
@@ -32,8 +32,8 @@
<controller type='pci' index='6' model='pcie-root-port' />
<controller type='pci' index='7' model='pcie-root-port' />
<!-- block -->
- <disk type='file' device='disk' iothread='1'>
- <driver name='qemu' type='raw'/>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='raw' iothread='1'/>
<source file='/path/to/rootfs'/>
<target dev='hda' bus='virtio'/>
<iotune>
@@ -66,7 +66,7 @@
<!-- rng -->
<rng model='virtio'>
<rate period='1000' bytes='1234'/>
- <backend model='random'>/dev/random</backend>
+ <backend model='random'>/path/to/random_file</backend>
<address type='pci' domain='0x000' bus='0x05' slot='0x00' function='0x00'/>
</rng>
<!-- vsock -->
@@ -75,7 +75,7 @@
<address type='pci' domain='0x000' bus='0x06' slot='0x00' function='0x00'/>
</vsock>
<!-- vfio -->
- <hostdev model='subsystem' type='pci' managed='yes'>
+ <hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
--
2.25.1

View File

@ -1,449 +0,0 @@
From 515c87cad45e324286b36b6c2f3d7f8319092a1e Mon Sep 17 00:00:00 2001
From: DBJ <974658390@qq.com>
Date: Fri, 13 Aug 2021 02:20:28 -0700
Subject: [PATCH 1/8] fix spelling errors in project
---
address_space/src/address_space.rs | 2 +-
boot_loader/src/x86_64/standard_boot/elf.rs | 2 +-
cpu/src/lib.rs | 8 ++++----
devices/src/interrupt_controller/aarch64/state.rs | 2 +-
devices/src/legacy/fwcfg.rs | 6 +++---
devices/src/legacy/pl011.rs | 2 +-
devices/src/legacy/rtc.rs | 6 +++---
docs/config_guidebook.md | 6 +++---
docs/design.md | 2 +-
docs/interconnect_with_libvirt.md | 2 +-
hypervisor/src/kvm/interrupt.rs | 2 +-
machine/src/micro_vm/mod.rs | 4 ++--
machine/src/standard_vm/aarch64/mod.rs | 2 +-
migration/src/manager.rs | 4 ++--
migration/src/snapshot.rs | 4 ++--
ozone/src/syscall.rs | 2 +-
tests/hydropper/monitor/monitor_thread.py | 2 +-
.../microvm/functional/test_microvm_concurrency.py | 4 ++--
tests/hydropper/utils/session.py | 2 +-
tests/hydropper/utils/utils_qmp.py | 2 +-
vfio/src/vfio_dev.rs | 8 ++++----
virtio/src/queue.rs | 2 +-
virtio/src/virtio_mmio.rs | 2 +-
23 files changed, 39 insertions(+), 39 deletions(-)
diff --git a/address_space/src/address_space.rs b/address_space/src/address_space.rs
index c182281..85bf71f 100644
--- a/address_space/src/address_space.rs
+++ b/address_space/src/address_space.rs
@@ -307,7 +307,7 @@ impl AddressSpace {
})
}
- /// Return the end address fo memory according to all Ram regions in AddressSpace.
+ /// Return the end address of memory according to all Ram regions in AddressSpace.
pub fn memory_end_address(&self) -> GuestAddress {
self.flat_view
.load()
diff --git a/boot_loader/src/x86_64/standard_boot/elf.rs b/boot_loader/src/x86_64/standard_boot/elf.rs
index 481b876..a76e789 100644
--- a/boot_loader/src/x86_64/standard_boot/elf.rs
+++ b/boot_loader/src/x86_64/standard_boot/elf.rs
@@ -79,7 +79,7 @@ impl Elf64Header {
bail!("Invalid magic in ELF header");
}
if self.e_ident[EI_DATA] != ELFDATA2LSB {
- bail!("Big endian ELF file is not suppored");
+ bail!("Big endian ELF file is not supported");
}
if self.e_ident[EI_CLASS] != ELFCLASS64 {
bail!("Only 64-bit ELF image is supported");
diff --git a/cpu/src/lib.rs b/cpu/src/lib.rs
index 41e143f..cb1a41b 100644
--- a/cpu/src/lib.rs
+++ b/cpu/src/lib.rs
@@ -494,7 +494,7 @@ impl CPUInterface for CPU {
.chain_err(|| "Some error occurred in guest shutdown")?;
} else {
error!(
- "Vcpu{} recevied unexpected system event with type 0x{:x}, flags 0x{:x}",
+ "Vcpu{} received unexpected system event with type 0x{:x}, flags 0x{:x}",
self.id(),
event,
flags
@@ -569,11 +569,11 @@ impl CPUThreadWorker {
}
register_signal_handler(VCPU_EXIT_SIGNAL, handle_signal)
- .chain_err(|| "Failed to registe VCPU_EXIT_SIGNAL signal.")?;
+ .chain_err(|| "Failed to register VCPU_EXIT_SIGNAL signal.")?;
register_signal_handler(VCPU_PAUSE_SIGNAL, handle_signal)
- .chain_err(|| "Failed to registe VCPU_PAUSE_SIGNAL signal.")?;
+ .chain_err(|| "Failed to register VCPU_PAUSE_SIGNAL signal.")?;
register_signal_handler(VCPU_TASK_SIGNAL, handle_signal)
- .chain_err(|| "Failed to registe VCPU_TASK_SIGNAL signal.")?;
+ .chain_err(|| "Failed to register VCPU_TASK_SIGNAL signal.")?;
Ok(())
}
diff --git a/devices/src/interrupt_controller/aarch64/state.rs b/devices/src/interrupt_controller/aarch64/state.rs
index e1b05b6..d4da00b 100644
--- a/devices/src/interrupt_controller/aarch64/state.rs
+++ b/devices/src/interrupt_controller/aarch64/state.rs
@@ -75,7 +75,7 @@ const ICC_CTLR_EL1: u64 = 0xc664;
const ICC_SRE_EL1: u64 = 0xc665;
const ICC_IGRPEN0_EL1: u64 = 0xc666;
const ICC_IGRPEN1_EL1: u64 = 0xc667;
-/// GICv3 CPU interface control regiter pribits[8:10]
+/// GICv3 CPU interface control register pribits[8:10]
const ICC_CTLR_EL1_PRIBITS_MASK: u64 = 0x700;
const ICC_CTLR_EL1_PRIBITS_SHIFT: u64 = 0x8;
diff --git a/devices/src/legacy/fwcfg.rs b/devices/src/legacy/fwcfg.rs
index ed41581..34c1375 100644
--- a/devices/src/legacy/fwcfg.rs
+++ b/devices/src/legacy/fwcfg.rs
@@ -365,7 +365,7 @@ impl FwCfgCommon {
);
};
- // unwrap is safe bacause the count of arch_entries and entries is initialized
+ // unwrap is safe because the count of arch_entries and entries is initialized
// as `FW_CFG_FILE_FIRST + FW_CFG_FILE_SLOTS_DFLT`, which is equal to the return
// value of `max_entry` function.
if self.is_arch_local() {
@@ -1402,7 +1402,7 @@ mod test {
fwcfg_dev.lock().unwrap().read(&mut read_data, base, offset);
assert_eq!(read_data, sig_entry_data);
- // Failed to write beacuse of offset overflow.
+ // Failed to write because of offset overflow.
let write_data = vec![0x0_u8];
let offset = 0x18;
let f_back = fwcfg_dev.lock().unwrap().write(&write_data, base, offset);
@@ -1442,7 +1442,7 @@ mod test {
fwcfg_dev.lock().unwrap().read(&mut read_data, base, offset);
assert_eq!(read_data, sig_entry_data);
- // Failed to write beacuse of offset overflow.
+ // Failed to write because of offset overflow.
let write_data = vec![0x0_u8];
let offset = 0x0c;
let f_back = fwcfg_dev.lock().unwrap().write(&write_data, base, offset);
diff --git a/devices/src/legacy/pl011.rs b/devices/src/legacy/pl011.rs
index fa063c3..133487e 100644
--- a/devices/src/legacy/pl011.rs
+++ b/devices/src/legacy/pl011.rs
@@ -74,7 +74,7 @@ pub struct PL011State {
ibrd: u32,
/// Fractional Baud Rate Register.
fbrd: u32,
- /// Interrut FIFO Level Select Register.
+ /// Interrupt FIFO Level Select Register.
ifl: u32,
/// Identifier Register. Length is 8.
id: [u8; 8],
diff --git a/devices/src/legacy/rtc.rs b/devices/src/legacy/rtc.rs
index 0b5e4aa..6241e68 100644
--- a/devices/src/legacy/rtc.rs
+++ b/devices/src/legacy/rtc.rs
@@ -36,7 +36,7 @@ const RTC_MINUTES: u8 = 0x02;
const RTC_MINUTES_ALARM: u8 = 0x03;
const RTC_HOURS: u8 = 0x04;
const RTC_HOURS_ARARM: u8 = 0x05;
-const RTC_DAY_OF_WEAK: u8 = 0x06;
+const RTC_DAY_OF_WEEK: u8 = 0x06;
const RTC_DAY_OF_MONTH: u8 = 0x07;
const RTC_MONTH: u8 = 0x08;
const RTC_YEAR: u8 = 0x09;
@@ -61,7 +61,7 @@ const CMOS_MEM_ABOVE_4GB: (u8, u8, u8) = (0x5B, 0x5C, 0x5D);
fn get_utc_time() -> libc::tm {
let time_val: libc::time_t = 0_i64;
- // Safe bacause `libc::time` only get time.
+ // Safe because `libc::time` only get time.
unsafe { libc::time(time_val as *mut i64) };
let mut dest_tm = libc::tm {
@@ -177,7 +177,7 @@ impl RTC {
RTC_HOURS => {
data[0] = bin_to_bcd(tm.tm_hour as u8);
}
- RTC_DAY_OF_WEAK => {
+ RTC_DAY_OF_WEEK => {
data[0] = bin_to_bcd((tm.tm_wday + 1) as u8);
}
RTC_DAY_OF_MONTH => {
diff --git a/docs/config_guidebook.md b/docs/config_guidebook.md
index 6d118ec..6a5cda7 100644
--- a/docs/config_guidebook.md
+++ b/docs/config_guidebook.md
@@ -124,7 +124,7 @@ If you want to use initrd as rootfs, `root=/dev/ram` and `rdinit=/bin/sh` must b
## 2. Device Configuration
For machine type "microvm", only virtio-mmio and legacy devices are supported.
-Maximum number of user createable devices is 11 on x86_64 and 160 on aarch64.
+Maximum number of user creatable devices is 11 on x86_64 and 160 on aarch64.
For standard VM (machine type "q35" on x86_64, and "virt" on aarch64) , virtio-pci devices are supported instead of virtio-mmio
devices. As for now pci bridges are not implemented yet, there is currently only one
@@ -829,7 +829,7 @@ About the arguments:
* `netns` : path to a existed network namespace.
* `source` : path to the source file, such as `rootfs` and `vmlinux`.
* `clean-resource` : a flag to clean resource.
-* `--` : these two dashes are used to splite args, the args followed are used to launched StratoVirt.
+* `--` : these two dashes are used to split args, the args followed are used to launched StratoVirt.
### 5.2 Example
As ozone uses a directory to mount as a root directory, after ozone is launched, the directory "/srv/zozne/{exec_file}/{name}" will be created. (Where, `exec_file` is the executable binary file, usually it is `stratovirt`, while `name` is the name of ozone, it is given by users, but the length of it should be no more than 255 bytes.) In order to run ozone normally, please make sure that the directory "/srv/zozne/{exec_file}/{name}" does not exists before launching ozone.
@@ -874,7 +874,7 @@ $ ./ozone \
```
## 6. Libvirt
-Libvirt launchs StratoVirt by creating cmdlines. But some of these commands
+Libvirt launches StratoVirt by creating cmdlines. But some of these commands
such as: cpu, overcommit, uuid, no-user-config, nodefaults, sandbox, msg, rtc, no-shutdown,
nographic, realtime, display, usb, mem-prealloc and boot, are not supported by StratoVirt.
To launch StratoVirt from libvirt successfully, StratoVirt needs to put these arguments into
diff --git a/docs/design.md b/docs/design.md
index 4ffdd16..537d256 100644
--- a/docs/design.md
+++ b/docs/design.md
@@ -45,6 +45,6 @@ The following figure shows StratoVirt's core architecture which consist of three
- Only the Linux operating system is supported; The recommended kernel version is 4.19;
- Only Linux is supported as the client operating system, and the recommended kernel version is 4.19;
-- StratoVirt is fullly tested on openEuler;
+- StratoVirt is fully tested on openEuler;
- Supports a maximum of 254 CPUs;
diff --git a/docs/interconnect_with_libvirt.md b/docs/interconnect_with_libvirt.md
index a448bb5..d5205ed 100644
--- a/docs/interconnect_with_libvirt.md
+++ b/docs/interconnect_with_libvirt.md
@@ -20,7 +20,7 @@ CPU topology is not supported, please configure the number of VCPUs only.
```
<vcpu>4</vcpu>
```
-- Archtecture:
+- Architecture:
Optional value of `arch` are: `aarch64` and `x86_64`. On X86 platform, supported machine is `q35`; on aarch 64 platform, supported machine is `virt`.
```
diff --git a/hypervisor/src/kvm/interrupt.rs b/hypervisor/src/kvm/interrupt.rs
index 45799f9..675d25c 100644
--- a/hypervisor/src/kvm/interrupt.rs
+++ b/hypervisor/src/kvm/interrupt.rs
@@ -103,7 +103,7 @@ impl IrqRouteTable {
#[cfg(target_arch = "x86_64")]
pub fn init_irq_route_table(&mut self) {
// On x86, use `kvm_create_irqchip` to create an interrupt
- // controller module in the kernel. It creates a virual PIC, a virtual ioapic,
+ // controller module in the kernel. It creates a virtual PIC, a virtual ioapic,
// and sets up future vcpus to have a local APIC. IRQ routing for GSIs 0-15 is set
// to both PIC and IOAPIC. GSI 16-23 only go to the IOAPIC.
for i in 0..IOAPIC_NUM_PINS {
diff --git a/machine/src/micro_vm/mod.rs b/machine/src/micro_vm/mod.rs
index ea92164..f48a6dc 100644
--- a/machine/src/micro_vm/mod.rs
+++ b/machine/src/micro_vm/mod.rs
@@ -659,7 +659,7 @@ impl MachineOps for LightMachine {
let index = MMIO_REPLACEABLE_BLK_NR + self.replaceable_info.net_count;
if index >= MMIO_REPLACEABLE_BLK_NR + MMIO_REPLACEABLE_NET_NR {
bail!(
- "A maximum of {} net replaceble devices are supported.",
+ "A maximum of {} net replaceable devices are supported.",
MMIO_REPLACEABLE_NET_NR
);
}
@@ -677,7 +677,7 @@ impl MachineOps for LightMachine {
let device_cfg = parse_blk(vm_config, cfg_args)?;
if self.replaceable_info.block_count >= MMIO_REPLACEABLE_BLK_NR {
bail!(
- "A maximum of {} block replaceble devices are supported.",
+ "A maximum of {} block replaceable devices are supported.",
MMIO_REPLACEABLE_BLK_NR
);
}
diff --git a/machine/src/standard_vm/aarch64/mod.rs b/machine/src/standard_vm/aarch64/mod.rs
index ee66bc9..54c103c 100644
--- a/machine/src/standard_vm/aarch64/mod.rs
+++ b/machine/src/standard_vm/aarch64/mod.rs
@@ -179,7 +179,7 @@ impl StdMachineOps for StdMachine {
let pcihost_root = PciHostRoot::new(root_bus);
pcihost_root
.realize()
- .chain_err(|| "Faile to realize pcihost root device.")?;
+ .chain_err(|| "Failed to realize pcihost root device.")?;
Ok(())
}
diff --git a/migration/src/manager.rs b/migration/src/manager.rs
index 35ed975..480b59b 100644
--- a/migration/src/manager.rs
+++ b/migration/src/manager.rs
@@ -21,7 +21,7 @@ use super::status::MigrationStatus;
use util::byte_code::ByteCode;
lazy_static! {
- /// Glocal MigrationMananger to manage all migration combined interface.
+ /// Glocal MigrationManager to manage all migration combined interface.
pub(crate) static ref MIGRATION_MANAGER: Arc<MigrationManager> = Arc::new(MigrationManager {
entry: Arc::new(RwLock::new(BTreeMap::<u64, MigrationEntry>::new())),
desc_db: Arc::new(RwLock::new(HashMap::<String, DeviceStateDesc>::new())),
@@ -135,7 +135,7 @@ pub enum MigrationEntry {
/// This structure is to manage all resource during migration.
/// It is also the only way to call on `MIGRATION_MANAGER`.
pub struct MigrationManager {
- /// The map offers the deivce_id and combined migratable device entry.
+ /// The map offers the device_id and combined migratable device entry.
pub(crate) entry: Arc<RwLock<BTreeMap<u64, MigrationEntry>>>,
/// The map offers the device type and its device state describe structure.
pub(crate) desc_db: Arc<RwLock<HashMap<String, DeviceStateDesc>>>,
diff --git a/migration/src/snapshot.rs b/migration/src/snapshot.rs
index 470ea63..edea8ce 100644
--- a/migration/src/snapshot.rs
+++ b/migration/src/snapshot.rs
@@ -94,7 +94,7 @@ impl MigrationManager {
/// # Notes
///
/// Offers a interface for restore snapshot functions. This function will make VM
- /// back to the state restored in snapshot file incluing both device and memory.
+ /// back to the state restored in snapshot file including both device and memory.
///
/// # Argument
///
@@ -126,7 +126,7 @@ impl MigrationManager {
bail!("Invalid device state snapshot file");
}
- Self::load_memory(&mut memory_file).chain_err(|| "Failed to load snpashot memory")?;
+ Self::load_memory(&mut memory_file).chain_err(|| "Failed to load snapshot memory")?;
let snapshot_desc_db =
Self::load_descriptor_db(&mut device_state_file, device_state_header.desc_len)
.chain_err(|| "Failed to load device descriptor db")?;
diff --git a/ozone/src/syscall.rs b/ozone/src/syscall.rs
index 2627642..936661f 100644
--- a/ozone/src/syscall.rs
+++ b/ozone/src/syscall.rs
@@ -140,7 +140,7 @@ pub fn set_host_name(host_name: &str) -> Result<()> {
///
/// # Arguments
///
-/// * `fd` - File descriptor refering to one of magic links in a /proc/[pid]/ns/ directory.
+/// * `fd` - File descriptor referring to one of magic links in a /proc/[pid]/ns/ directory.
/// * `nstype` - Namespace type.
pub fn setns(fd: i32, nstype: i32) -> Result<()> {
SyscallResult {
diff --git a/tests/hydropper/monitor/monitor_thread.py b/tests/hydropper/monitor/monitor_thread.py
index daad97d..5921ecf 100644
--- a/tests/hydropper/monitor/monitor_thread.py
+++ b/tests/hydropper/monitor/monitor_thread.py
@@ -25,7 +25,7 @@ class MonitorThread(threading.Thread):
items = dict()
def __init__(self):
- """Construtor"""
+ """Constructor"""
super(MonitorThread, self).__init__()
self.state_lock = threading.Lock()
self._state = 'init'
diff --git a/tests/hydropper/testcases/microvm/functional/test_microvm_concurrency.py b/tests/hydropper/testcases/microvm/functional/test_microvm_concurrency.py
index ded87ad..73de004 100644
--- a/tests/hydropper/testcases/microvm/functional/test_microvm_concurrency.py
+++ b/tests/hydropper/testcases/microvm/functional/test_microvm_concurrency.py
@@ -20,10 +20,10 @@ def test_microvm_concurrency(microvms):
"""
Test multi microvms start:
- 1) Set each VM vcpu_count = 4, then launch it and comfirm vcpu count is 4.
+ 1) Set each VM vcpu_count = 4, then launch it and confirm vcpu count is 4.
And increase _succ_sum.
2) Execute step 1 concurrency by threads.
- 3) Comfirm each VM is execute successffully by _succ_sum
+ 3) Confirm each VM is execute successffully by _succ_sum
Note: You can modify CONCURRENT_QUANTITY tag in config/config.ini to set vm quantity.
"""
diff --git a/tests/hydropper/utils/session.py b/tests/hydropper/utils/session.py
index 1eb3bad..bb9036f 100644
--- a/tests/hydropper/utils/session.py
+++ b/tests/hydropper/utils/session.py
@@ -152,7 +152,7 @@ class ConsoleManager():
LOG.debug("Got 'Warning added RSA to known host list")
continue
except aexpect.ExpectTimeoutError as err:
- # send a empty line to avoid unexpect login timeout
+ # send a empty line to avoid unexpected login timeout
# because some message from linux kernel maybe impact match
if not last_chance:
time.sleep(0.5)
diff --git a/tests/hydropper/utils/utils_qmp.py b/tests/hydropper/utils/utils_qmp.py
index 8acefed..7d0527d 100644
--- a/tests/hydropper/utils/utils_qmp.py
+++ b/tests/hydropper/utils/utils_qmp.py
@@ -9,7 +9,7 @@
# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
# NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
-"""Some qmp fuctions"""
+"""Some qmp functions"""
import re
from utils.exception import QMPError
diff --git a/vfio/src/vfio_dev.rs b/vfio/src/vfio_dev.rs
index 0603d49..30f7d5a 100644
--- a/vfio/src/vfio_dev.rs
+++ b/vfio/src/vfio_dev.rs
@@ -464,13 +464,13 @@ impl VfioDevice {
.iter()
.collect::<PathBuf>()
.read_link()
- .chain_err(|| "Invaild iommu group path")?;
+ .chain_err(|| "Invalid iommu group path")?;
let group_name = iommu_group
.file_name()
- .chain_err(|| "Invaild iommu group name")?;
+ .chain_err(|| "Invalid iommu group name")?;
let mut group_id = 0;
if let Some(n) = group_name.to_str() {
- group_id = n.parse::<u32>().chain_err(|| "Invaild iommu group id")?;
+ group_id = n.parse::<u32>().chain_err(|| "Invalid iommu group id")?;
}
let mut groups = container.groups.lock().unwrap();
@@ -489,7 +489,7 @@ impl VfioDevice {
fn vfio_get_device(group: &VfioGroup, name: &Path) -> Result<File> {
let mut dev_name: &str = "";
if let Some(n) = name.file_name() {
- dev_name = n.to_str().chain_err(|| "Invaild device path")?;
+ dev_name = n.to_str().chain_err(|| "Invalid device path")?;
}
let path: CString = CString::new(dev_name.as_bytes())
.chain_err(|| "Failed to convert device name to CString type of data")?;
diff --git a/virtio/src/queue.rs b/virtio/src/queue.rs
index 9979b5c..6ac137c 100644
--- a/virtio/src/queue.rs
+++ b/virtio/src/queue.rs
@@ -68,7 +68,7 @@ pub struct QueueConfig {
pub ready: bool,
/// Interrupt vector index of the queue for msix
pub vector: u16,
- /// The next index which can be poped in the available vring.
+ /// The next index which can be popped in the available vring.
next_avail: u16,
/// The next index which can be pushed in the used vring.
next_used: u16,
diff --git a/virtio/src/virtio_mmio.rs b/virtio/src/virtio_mmio.rs
index 099015f..ad9b32a 100644
--- a/virtio/src/virtio_mmio.rs
+++ b/virtio/src/virtio_mmio.rs
@@ -80,7 +80,7 @@ const VENDOR_ID: u32 = 0;
const MMIO_MAGIC_VALUE: u32 = 0x7472_6976;
const MMIO_VERSION: u32 = 2;
-/// The maximun of virtio queue within a virtio device.
+/// The maximum of virtio queue within a virtio device.
const MAXIMUM_NR_QUEUES: usize = 8;
/// HostNotifyInfo includes the info needed for notifying backend from guest.
--
2.25.1

View File

@ -1,55 +0,0 @@
From cde02263b76a88407b23d0ca2e06f244c45dec42 Mon Sep 17 00:00:00 2001
From: Wei Gao <gaowei66@huawei.com>
Date: Thu, 19 Aug 2021 20:13:42 +0800
Subject: [PATCH 5/8] kernel_config: update kernel config 5.10 on aarch64
platform.
1. Turn on memory hotplug feature.
Signed-off-by: Wei Gao <gaowei66@huawei.com>
---
docs/kernel_config/micro_vm/kernel_config_5.10_aarch64 | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/docs/kernel_config/micro_vm/kernel_config_5.10_aarch64 b/docs/kernel_config/micro_vm/kernel_config_5.10_aarch64
index d9deb7a..bbd016f 100644
--- a/docs/kernel_config/micro_vm/kernel_config_5.10_aarch64
+++ b/docs/kernel_config/micro_vm/kernel_config_5.10_aarch64
@@ -698,7 +698,9 @@ CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
CONFIG_SPARSEMEM_VMEMMAP=y
CONFIG_HAVE_FAST_GUP=y
CONFIG_ARCH_KEEP_MEMBLOCK=y
-# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_MEMORY_ISOLATION=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTPLUG_SPARSE=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MEMORY_BALLOON=y
# CONFIG_COMPACTION is not set
@@ -1767,6 +1769,7 @@ CONFIG_COMMON_CLK=y
# CONFIG_CLK_QORIQ is not set
# CONFIG_COMMON_CLK_XGENE is not set
# CONFIG_COMMON_CLK_FIXED_MMIO is not set
+# CONFIG_MCHP_CLK_PFSOC is not set
# CONFIG_HWSPINLOCK is not set
#
@@ -2072,6 +2075,8 @@ CONFIG_INIT_STACK_NONE=y
# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set
# end of Memory initialization
# end of Kernel hardening options
+
+# CONFIG_SECURITY_BOOT_INIT is not set
# end of Security options
CONFIG_CRYPTO=y
@@ -2431,4 +2436,4 @@ CONFIG_CC_HAS_SANCOV_TRACE_PC=y
# CONFIG_RUNTIME_TESTING_MENU is not set
# CONFIG_MEMTEST is not set
# end of Kernel Testing and Coverage
-# end of Kernel hacking
\ No newline at end of file
+# end of Kernel hacking
--
2.25.1

View File

@ -1,146 +0,0 @@
From 7e9ea7ef5f9673d40cf64fcd306c879028d39c29 Mon Sep 17 00:00:00 2001
From: Ming Yang <yangming73@huawei.com>
Date: Sat, 28 Aug 2021 10:32:38 +0800
Subject: [PATCH 09/10] machine: add init_multifunction function to init
multifunction.
Signed-off-by: Xinle.Guo <guoxinle1@huawei.com>
Signed-off-by: Ming Yang <yangming73@huawei.com>
---
pci/src/config.rs | 2 ++
pci/src/lib.rs | 88 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 89 insertions(+), 1 deletion(-)
diff --git a/pci/src/config.rs b/pci/src/config.rs
index 873fe7a..812001d 100644
--- a/pci/src/config.rs
+++ b/pci/src/config.rs
@@ -27,6 +27,8 @@ pub const PCI_CONFIG_SPACE_SIZE: usize = 256;
pub const PCIE_CONFIG_SPACE_SIZE: usize = 4096;
/// Size in bytes of dword.
pub const REG_SIZE: usize = 4;
+/// Max number of function.
+pub const MAX_FUNC: u8 = 8;
/// Vendor ID Register.
pub const VENDOR_ID: u8 = 0x0;
diff --git a/pci/src/lib.rs b/pci/src/lib.rs
index 8f11ad4..dfcbd71 100644
--- a/pci/src/lib.rs
+++ b/pci/src/lib.rs
@@ -46,11 +46,15 @@ pub mod msix;
mod root_port;
pub use bus::PciBus;
+use config::{HEADER_TYPE, HEADER_TYPE_MULTIFUNC, MAX_FUNC};
pub use host::PciHost;
pub use msix::init_msix;
pub use root_port::RootPort;
-use std::mem::size_of;
+use std::{
+ mem::size_of,
+ sync::{Mutex, Weak},
+};
use byteorder::{ByteOrder, LittleEndian};
@@ -105,6 +109,18 @@ le_read!(le_read_u16, read_u16, u16);
le_read!(le_read_u32, read_u32, u32);
le_read!(le_read_u64, read_u64, u64);
+pub fn pci_devfn(slot: u8, func: u8) -> u8 {
+ ((slot & 0x1f) << 3) | (func & 0x07)
+}
+
+pub fn pci_slot(devfn: u8) -> u8 {
+ devfn >> 3 & 0x1f
+}
+
+pub fn pci_func(devfn: u8) -> u8 {
+ devfn & 0x07
+}
+
pub trait PciDevOps: Send {
/// Init writable bit mask.
fn init_write_mask(&mut self) -> Result<()>;
@@ -150,6 +166,76 @@ pub trait PciDevOps: Send {
fn name(&self) -> String;
}
+/// Init multifunction for pci devices.
+///
+/// # Arguments
+///
+/// * `multifunction` - Whether to open multifunction.
+/// * `config` - Configuration space of pci devices.
+/// * `devfn` - Devfn number.
+/// * `parent_bus` - Parent bus of pci devices.
+pub fn init_multifunction(
+ multifunction: bool,
+ config: &mut Vec<u8>,
+ devfn: u8,
+ parent_bus: Weak<Mutex<PciBus>>,
+) -> Result<()> {
+ let mut header_type =
+ le_read_u16(&config, HEADER_TYPE as usize)? & (!HEADER_TYPE_MULTIFUNC as u16);
+ if multifunction {
+ header_type |= HEADER_TYPE_MULTIFUNC as u16;
+ }
+ le_write_u16(config, HEADER_TYPE as usize, header_type as u16)?;
+
+ // Allow two ways of multifunction bit:
+ // 1. The multifunction bit of all devices must be set;
+ // 2. Function 0 must set the bit, the rest function (1~7) is allowed to
+ // leave the bit to 0.
+ let slot = pci_slot(devfn);
+ let bus = parent_bus.upgrade().unwrap();
+ let locked_bus = bus.lock().unwrap();
+ if pci_func(devfn) != 0 {
+ let pci_dev = locked_bus.devices.get(&pci_devfn(slot, 0));
+ if pci_dev.is_none() {
+ return Ok(());
+ }
+
+ let mut data = vec![0_u8; 2];
+ pci_dev
+ .unwrap()
+ .lock()
+ .unwrap()
+ .read_config(HEADER_TYPE as usize, data.as_mut_slice());
+ if LittleEndian::read_u16(&data) & HEADER_TYPE_MULTIFUNC as u16 == 0 {
+ // Function 0 should set multifunction bit.
+ bail!(
+ "PCI: single function device can't be populated in bus {} function {}.{}",
+ &locked_bus.name,
+ slot,
+ devfn & 0x07
+ );
+ }
+ return Ok(());
+ }
+
+ if multifunction {
+ return Ok(());
+ }
+
+ // If function 0 is set to single function, the rest function should be None.
+ for func in 1..MAX_FUNC {
+ if locked_bus.devices.get(&pci_devfn(slot, func)).is_some() {
+ bail!(
+ "PCI: {}.0 indicates single function, but {}.{} is already populated",
+ slot,
+ slot,
+ func
+ );
+ }
+ }
+ Ok(())
+}
+
/// Check whether two regions overlap with each other.
///
/// # Arguments
--
2.25.1

View File

@ -1,636 +0,0 @@
From 4e8272a490b9901fc92fbaad1c10fee6d8b43fe3 Mon Sep 17 00:00:00 2001
From: Ming Yang <yangming73@huawei.com>
Date: Sat, 28 Aug 2021 10:33:25 +0800
Subject: [PATCH 10/10] machine: add realization for multifunction.
1. Add realization for multifunction of virtio pci devices,
vfio pci devices and pcie-root-port.
2. Add docs for multifunction.
Signed-off-by: Xinle.Guo <guoxinle1@huawei.com>
Signed-off-by: Ming Yang <yangming73@huawei.com>
---
docs/config_guidebook.md | 14 ++--
machine/src/lib.rs | 93 +++++++++++++++++-----
machine/src/standard_vm/x86_64/ich9_lpc.rs | 10 ++-
pci/src/host.rs | 6 +-
pci/src/root_port.rs | 29 +++++--
vfio/src/vfio_pci.rs | 31 ++++++--
virtio/src/virtio_pci.rs | 53 +++++++++++-
7 files changed, 192 insertions(+), 44 deletions(-)
diff --git a/docs/config_guidebook.md b/docs/config_guidebook.md
index b1f7b08..946d155 100644
--- a/docs/config_guidebook.md
+++ b/docs/config_guidebook.md
@@ -212,7 +212,7 @@ is a single function device, the function number should be set to zero.
-device virtio-net-device,netdev=netdevid,id=netid[,iothread=iothread1,mac=12:34:56:78:9A:BC]
# virtio pci net device
-netdev tap,id=netdevid,ifname=host_dev_name
--device virtio-net-pci,netdev=netdevid,id=netid,bus=pcie.0,addr=0x2.0x0[,iothread=iothread1,mac=12:34:56:78:9A:BC]
+-device virtio-net-pci,netdev=netdevid,id=netid,bus=pcie.0,addr=0x2.0x0[,multifunction=on,iothread=iothread1,mac=12:34:56:78:9A:BC]
```
StratoVirt also supports vhost-net to get a higher performance in network. It can be set by
@@ -227,7 +227,7 @@ given when `vhost=on`, StratoVirt gets it by opening "/dev/vhost-net" automatica
-device virtio-net-device,netdev=netdevid,id=netid[,iothread=iothread1,mac=12:34:56:78:9A:BC]
# virtio pci net device
-netdev tap,id=netdevid,ifname=host_dev_name,vhost=on[,vhostfd=2]
--device virtio-net-pci,netdev=netdevid,id=netid,bus=pcie.0,addr=0x2.0x0[,iothread=iothread1,mac=12:34:56:78:9A:BC]
+-device virtio-net-pci,netdev=netdevid,id=netid,bus=pcie.0,addr=0x2.0x0[,multifunction=on,iothread=iothread1,mac=12:34:56:78:9A:BC]
```
*How to set a tap device?*
@@ -273,7 +273,7 @@ of device and the second one represents function number of it.
-device virtconsole,chardev=virtioconsole1,id=console_id
# virtio pci device
--device virtio-serial-pci,bus=pcie.0,addr=0x1[,id=virtio-serial0]
+-device virtio-serial-pci,bus=pcie.0,addr=0x1.0x0[,multifunction=on,id=virtio-serial0]
-chardev socket,path=socket_path,id=virtioconsole1,server,nowait
-device virtconsole,chardev=virtioconsole1,id=console_id
```
@@ -307,7 +307,7 @@ of device and the second one represents function number of it.
-device vhost-vsock-device,id=vsock_id,guest-cid=3
# virtio pci device.
--device vhost-vsock-pci,id=vsock_id,guest-cid=3,bus=pcie.0,addr=0x1.0x0
+-device vhost-vsock-pci,id=vsock_id,guest-cid=3,bus=pcie.0,addr=0x1.0x0[,multifunction=on]
```
*You can only set one virtio vsock device for one VM.*
@@ -363,7 +363,7 @@ of device and the second one represents function number of it.
# virtio mmio balloon device
-device virtio-balloon-device,deflate-on-oom=true
# virtio pci balloon device
--device virtio-balloon-pci,bus=pcie.0,addr=0x4.0x0,deflate-on-oom=true
+-device virtio-balloon-pci,bus=pcie.0,addr=0x4.0x0,deflate-on-oom=true[,multifunction=on]
```
### 2.8 Virtio-rng
@@ -396,7 +396,7 @@ single function device, the function number should be set to zero.
-device virtio-rng-device,rng=objrng0,max-bytes=1234,period=1000
# virtio pci rng device
-object rng-random,id=objrng0,filename=/path/to/random_file
--device virtio-rng-pci,rng=objrng0,max-bytes=1234,period=1000,bus=pcie.0,addr=0x1
+-device virtio-rng-pci,rng=objrng0,max-bytes=1234,period=1000,bus=pcie.0,addr=0x1.0x0[,multifunction=on]
```
### 2.9 PCIe root port
@@ -458,7 +458,7 @@ Four properties are supported for VFIO device
* addr: including slot number and function number.
```shell
# cmdline
--device vfio-pci,host=0000:1a:00.3,id=net,bus=pcie.0,addr=0x03
+-device vfio-pci,host=0000:1a:00.3,id=net,bus=pcie.0,addr=0x03.0x0[,multifunction=on]
```
### 2.12 Chardev
diff --git a/machine/src/lib.rs b/machine/src/lib.rs
index 22aed89..23394ef 100644
--- a/machine/src/lib.rs
+++ b/machine/src/lib.rs
@@ -123,9 +123,9 @@ use devices::InterruptController;
use hypervisor::KVM_FDS;
use kvm_ioctls::VcpuFd;
use machine_manager::config::{
- get_pci_bdf, parse_balloon, parse_blk, parse_net, parse_rng_dev, parse_root_port, parse_vfio,
- parse_virtconsole, parse_virtio_serial, parse_vsock, MachineMemConfig, PFlashConfig, PciBdf,
- SerialConfig, VfioConfig, VmConfig,
+ get_multi_function, get_pci_bdf, parse_balloon, parse_blk, parse_net, parse_rng_dev,
+ parse_root_port, parse_vfio, parse_virtconsole, parse_virtio_serial, parse_vsock,
+ MachineMemConfig, PFlashConfig, PciBdf, SerialConfig, VfioConfig, VmConfig,
};
use machine_manager::event_loop::EventLoop;
use machine_manager::machine::{KvmVmState, MachineInterface};
@@ -297,9 +297,16 @@ pub trait MachineOps {
);
} else {
let bdf = get_pci_bdf(cfg_args)?;
+ let multi_func = get_multi_function(cfg_args)?;
let (devfn, parent_bus) = self.get_devfn_and_parent_bus(&bdf)?;
- let virtio_pci_device =
- VirtioPciDevice::new(device_cfg.id, devfn, sys_mem, vsock.clone(), parent_bus);
+ let virtio_pci_device = VirtioPciDevice::new(
+ device_cfg.id,
+ devfn,
+ sys_mem,
+ vsock.clone(),
+ parent_bus,
+ multi_func,
+ );
virtio_pci_device
.realize()
.chain_err(|| "Failed to add virtio pci vsock device")?;
@@ -342,9 +349,11 @@ pub trait MachineOps {
} else {
let name = device_cfg.id;
let bdf = get_pci_bdf(cfg_args)?;
+ let multi_func = get_multi_function(cfg_args)?;
let (devfn, parent_bus) = self.get_devfn_and_parent_bus(&bdf)?;
let sys_mem = self.get_sys_mem().clone();
- let virtio_pci_device = VirtioPciDevice::new(name, devfn, sys_mem, balloon, parent_bus);
+ let virtio_pci_device =
+ VirtioPciDevice::new(name, devfn, sys_mem, balloon, parent_bus, multi_func);
virtio_pci_device
.realize()
.chain_err(|| "Failed to add virtio pci balloon device")?;
@@ -373,16 +382,24 @@ pub trait MachineOps {
);
} else {
let name = device_cfg.id;
- let bdf = if let Some(virtio_serial_info) = &vm_config.virtio_serial {
- // Reasonable, because for virtio-serial-pci device, the bdf has been checked.
- virtio_serial_info.pci_bdf.clone().unwrap()
+ let virtio_serial_info = if let Some(serial_info) = &vm_config.virtio_serial {
+ serial_info
} else {
- bail!("No pci BDF configured for virtconsole");
+ bail!("No virtio-serial-pci device configured for virtconsole");
};
+ // Reasonable, because for virtio-serial-pci device, the bdf has been checked.
+ let bdf = virtio_serial_info.pci_bdf.clone().unwrap();
+ let multi_func = virtio_serial_info.multifunction;
let (devfn, parent_bus) = self.get_devfn_and_parent_bus(&bdf)?;
let sys_mem = self.get_sys_mem().clone();
- let virtio_pci_device =
- VirtioPciDevice::new(name, devfn, sys_mem, console.clone(), parent_bus);
+ let virtio_pci_device = VirtioPciDevice::new(
+ name,
+ devfn,
+ sys_mem,
+ console.clone(),
+ parent_bus,
+ multi_func,
+ );
virtio_pci_device
.realize()
.chain_err(|| "Failed to add virtio pci console device")?;
@@ -416,10 +433,17 @@ pub trait MachineOps {
.chain_err(|| "Failed to add virtio mmio rng device")?;
} else {
let bdf = get_pci_bdf(cfg_args)?;
+ let multi_func = get_multi_function(cfg_args)?;
let (devfn, parent_bus) = self.get_devfn_and_parent_bus(&bdf)?;
let sys_mem = self.get_sys_mem().clone();
- let vitio_pci_device =
- VirtioPciDevice::new(device_cfg.id, devfn, sys_mem, rng_dev.clone(), parent_bus);
+ let vitio_pci_device = VirtioPciDevice::new(
+ device_cfg.id,
+ devfn,
+ sys_mem,
+ rng_dev.clone(),
+ parent_bus,
+ multi_func,
+ );
vitio_pci_device
.realize()
.chain_err(|| "Failed to add pci rng device")?;
@@ -434,6 +458,7 @@ pub trait MachineOps {
fn add_virtio_pci_blk(&mut self, vm_config: &mut VmConfig, cfg_args: &str) -> Result<()> {
let bdf = get_pci_bdf(cfg_args)?;
+ let multi_func = get_multi_function(cfg_args)?;
let (devfn, parent_bus) = self.get_devfn_and_parent_bus(&bdf)?;
let sys_mem = self.get_sys_mem();
let device_cfg = parse_blk(vm_config, cfg_args)?;
@@ -444,6 +469,7 @@ pub trait MachineOps {
sys_mem.clone(),
device.clone(),
parent_bus,
+ multi_func,
);
pcidev
.realize()
@@ -454,19 +480,34 @@ pub trait MachineOps {
fn add_virtio_pci_net(&mut self, vm_config: &mut VmConfig, cfg_args: &str) -> Result<()> {
let bdf = get_pci_bdf(cfg_args)?;
+ let multi_func = get_multi_function(cfg_args)?;
let (devfn, parent_bus) = self.get_devfn_and_parent_bus(&bdf)?;
let sys_mem = self.get_sys_mem();
let device_cfg = parse_net(vm_config, cfg_args)?;
let virtio_pci_device = if device_cfg.vhost_type.is_some() {
let device = Arc::new(Mutex::new(VhostKern::Net::new(&device_cfg, &sys_mem)));
- VirtioPciDevice::new(device_cfg.id, devfn, sys_mem.clone(), device, parent_bus)
+ VirtioPciDevice::new(
+ device_cfg.id,
+ devfn,
+ sys_mem.clone(),
+ device,
+ parent_bus,
+ multi_func,
+ )
} else {
let device = Arc::new(Mutex::new(virtio::Net::new(device_cfg.clone())));
MigrationManager::register_device_instance_mutex(
VirtioNetState::descriptor(),
device.clone(),
);
- VirtioPciDevice::new(device_cfg.id, devfn, sys_mem.clone(), device, parent_bus)
+ VirtioPciDevice::new(
+ device_cfg.id,
+ devfn,
+ sys_mem.clone(),
+ device,
+ parent_bus,
+ multi_func,
+ )
};
virtio_pci_device
.realize()
@@ -484,9 +525,17 @@ pub trait MachineOps {
let path = "/sys/bus/pci/devices/".to_string() + &device_cfg.host;
let name = device_cfg.id;
let bdf = get_pci_bdf(cfg_args)?;
+ let multi_func = get_multi_function(cfg_args)?;
let (devfn, parent_bus) = self.get_devfn_and_parent_bus(&bdf)?;
- let vfio_pci_dev = VfioPciDevice::new(Path::new(&path), container, devfn, name, parent_bus)
- .chain_err(|| "Failed to create vfio pci device")?;
+ let vfio_pci_dev = VfioPciDevice::new(
+ Path::new(&path),
+ container,
+ devfn,
+ name,
+ parent_bus,
+ multi_func,
+ )
+ .chain_err(|| "Failed to create vfio pci device")?;
VfioPciDevice::realize(vfio_pci_dev).chain_err(|| "Failed to realize vfio pci device")?;
Ok(())
@@ -513,7 +562,13 @@ pub trait MachineOps {
if PciBus::find_bus_by_name(&bus, &device_cfg.id).is_some() {
bail!("ID {} already exists.");
}
- let rootport = RootPort::new(device_cfg.id, devfn, device_cfg.port, parent_bus);
+ let rootport = RootPort::new(
+ device_cfg.id,
+ devfn,
+ device_cfg.port,
+ parent_bus,
+ device_cfg.multifunction,
+ );
rootport
.realize()
.chain_err(|| "Failed to add pci root port")?;
diff --git a/machine/src/standard_vm/x86_64/ich9_lpc.rs b/machine/src/standard_vm/x86_64/ich9_lpc.rs
index b5d7524..0b1b3d5 100644
--- a/machine/src/standard_vm/x86_64/ich9_lpc.rs
+++ b/machine/src/standard_vm/x86_64/ich9_lpc.rs
@@ -15,7 +15,10 @@ use std::sync::{Arc, Mutex, Weak};
use acpi::AcpiPMTimer;
use address_space::{AddressSpace, GuestAddress, Region, RegionOps};
use error_chain::ChainedError;
-use pci::config::{PciConfig, DEVICE_ID, PCI_CONFIG_SPACE_SIZE, SUB_CLASS_CODE, VENDOR_ID};
+use pci::config::{
+ PciConfig, DEVICE_ID, HEADER_TYPE, HEADER_TYPE_BRIDGE, HEADER_TYPE_MULTIFUNC,
+ PCI_CONFIG_SPACE_SIZE, SUB_CLASS_CODE, VENDOR_ID,
+};
use pci::errors::Result as PciResult;
use pci::{le_write_u16, le_write_u32, ranges_overlap, PciBus, PciDevOps};
use util::byte_code::ByteCode;
@@ -96,6 +99,11 @@ impl PciDevOps for LPCBridge {
CLASS_CODE_ISA_BRIDGE,
)?;
le_write_u32(&mut self.config.write_mask, PM_BASE_OFFSET as usize, 0xff80)?;
+ le_write_u16(
+ &mut self.config.config,
+ HEADER_TYPE as usize,
+ (HEADER_TYPE_BRIDGE | HEADER_TYPE_MULTIFUNC) as u16,
+ )?;
let parent_bus = self.parent_bus.clone();
parent_bus
diff --git a/pci/src/host.rs b/pci/src/host.rs
index 19bbee7..153ba14 100644
--- a/pci/src/host.rs
+++ b/pci/src/host.rs
@@ -440,7 +440,7 @@ pub mod tests {
let root_bus = Arc::downgrade(&pci_host.lock().unwrap().root_bus);
let pio_addr_ops = PciHost::build_pio_addr_ops(pci_host.clone());
let pio_data_ops = PciHost::build_pio_data_ops(pci_host.clone());
- let root_port = RootPort::new("pcie.1".to_string(), 8, 0, root_bus);
+ let root_port = RootPort::new("pcie.1".to_string(), 8, 0, root_bus, false);
root_port.realize().unwrap();
let mut data = [0_u8; 4];
@@ -517,10 +517,10 @@ pub mod tests {
let root_bus = Arc::downgrade(&pci_host.lock().unwrap().root_bus);
let mmconfig_region_ops = PciHost::build_mmconfig_ops(pci_host.clone());
- let mut root_port = RootPort::new("pcie.1".to_string(), 8, 0, root_bus.clone());
+ let mut root_port = RootPort::new("pcie.1".to_string(), 8, 0, root_bus.clone(), false);
root_port.write_config(SECONDARY_BUS_NUM as usize, &[1]);
root_port.realize().unwrap();
- let mut root_port = RootPort::new("pcie.2".to_string(), 16, 0, root_bus);
+ let mut root_port = RootPort::new("pcie.2".to_string(), 16, 0, root_bus, false);
root_port.write_config(SECONDARY_BUS_NUM as usize, &[2]);
root_port.realize().unwrap();
diff --git a/pci/src/root_port.rs b/pci/src/root_port.rs
index 948e31d..321c55e 100644
--- a/pci/src/root_port.rs
+++ b/pci/src/root_port.rs
@@ -20,12 +20,13 @@ use util::byte_code::ByteCode;
use super::config::{
PciConfig, PcieDevType, BAR_0, CLASS_CODE_PCI_BRIDGE, COMMAND, COMMAND_IO_SPACE,
- COMMAND_MEMORY_SPACE, DEVICE_ID, HEADER_TYPE, HEADER_TYPE_BRIDGE, HEADER_TYPE_MULTIFUNC,
- IO_BASE, MEMORY_BASE, PCIE_CONFIG_SPACE_SIZE, PCI_VENDOR_ID_REDHAT, PREF_MEMORY_BASE,
- PREF_MEMORY_LIMIT, PREF_MEM_RANGE_64BIT, REG_SIZE, SUB_CLASS_CODE, VENDOR_ID,
+ COMMAND_MEMORY_SPACE, DEVICE_ID, HEADER_TYPE, HEADER_TYPE_BRIDGE, IO_BASE, MEMORY_BASE,
+ PCIE_CONFIG_SPACE_SIZE, PCI_VENDOR_ID_REDHAT, PREF_MEMORY_BASE, PREF_MEMORY_LIMIT,
+ PREF_MEM_RANGE_64BIT, REG_SIZE, SUB_CLASS_CODE, VENDOR_ID,
};
use crate::bus::PciBus;
use crate::errors::{Result, ResultExt};
+use crate::init_multifunction;
use crate::msix::init_msix;
use crate::{le_read_u16, le_write_u16, ranges_overlap, PciDevOps};
@@ -56,6 +57,7 @@ pub struct RootPort {
io_region: Region,
mem_region: Region,
dev_id: u16,
+ multifunction: bool,
}
impl RootPort {
@@ -68,7 +70,13 @@ impl RootPort {
/// * `port_num` - Root port number.
/// * `parent_bus` - Weak reference to the parent bus.
#[allow(dead_code)]
- pub fn new(name: String, devfn: u8, port_num: u8, parent_bus: Weak<Mutex<PciBus>>) -> Self {
+ pub fn new(
+ name: String,
+ devfn: u8,
+ port_num: u8,
+ parent_bus: Weak<Mutex<PciBus>>,
+ multifunction: bool,
+ ) -> Self {
#[cfg(target_arch = "x86_64")]
let io_region = Region::init_container_region(1 << 16);
let mem_region = Region::init_container_region(u64::max_value());
@@ -90,6 +98,7 @@ impl RootPort {
io_region,
mem_region,
dev_id: 0,
+ multifunction,
}
}
}
@@ -113,9 +122,15 @@ impl PciDevOps for RootPort {
le_write_u16(config_space, VENDOR_ID as usize, PCI_VENDOR_ID_REDHAT)?;
le_write_u16(config_space, DEVICE_ID as usize, DEVICE_ID_RP)?;
le_write_u16(config_space, SUB_CLASS_CODE as usize, CLASS_CODE_PCI_BRIDGE)?;
- config_space[HEADER_TYPE as usize] = HEADER_TYPE_BRIDGE | HEADER_TYPE_MULTIFUNC;
+ config_space[HEADER_TYPE as usize] = HEADER_TYPE_BRIDGE;
config_space[PREF_MEMORY_BASE as usize] = PREF_MEM_RANGE_64BIT;
config_space[PREF_MEMORY_LIMIT as usize] = PREF_MEM_RANGE_64BIT;
+ init_multifunction(
+ self.multifunction,
+ config_space,
+ self.devfn,
+ self.parent_bus.clone(),
+ )?;
self.config
.add_pcie_cap(self.devfn, self.port_num, PcieDevType::RootPort as u8)?;
@@ -294,7 +309,7 @@ mod tests {
fn test_read_config() {
let pci_host = create_pci_host();
let root_bus = Arc::downgrade(&pci_host.lock().unwrap().root_bus);
- let root_port = RootPort::new("pcie.1".to_string(), 8, 0, root_bus);
+ let root_port = RootPort::new("pcie.1".to_string(), 8, 0, root_bus, false);
root_port.realize().unwrap();
let root_port = pci_host.lock().unwrap().find_device(0, 8).unwrap();
@@ -310,7 +325,7 @@ mod tests {
fn test_write_config() {
let pci_host = create_pci_host();
let root_bus = Arc::downgrade(&pci_host.lock().unwrap().root_bus);
- let root_port = RootPort::new("pcie.1".to_string(), 8, 0, root_bus);
+ let root_port = RootPort::new("pcie.1".to_string(), 8, 0, root_bus, false);
root_port.realize().unwrap();
let root_port = pci_host.lock().unwrap().find_device(0, 8).unwrap();
diff --git a/vfio/src/vfio_pci.rs b/vfio/src/vfio_pci.rs
index e366e47..40004a5 100644
--- a/vfio/src/vfio_pci.rs
+++ b/vfio/src/vfio_pci.rs
@@ -32,7 +32,7 @@ use pci::config::SECONDARY_BUS_NUM;
use pci::config::{
PciConfig, RegionType, BAR_0, BAR_5, BAR_IO_SPACE, BAR_MEM_64BIT, BAR_SPACE_UNMAPPED, COMMAND,
COMMAND_BUS_MASTER, COMMAND_INTERRUPT_DISABLE, COMMAND_IO_SPACE, COMMAND_MEMORY_SPACE,
- IO_BASE_ADDR_MASK, MEM_BASE_ADDR_MASK, PCIE_CONFIG_SPACE_SIZE, REG_SIZE,
+ HEADER_TYPE, IO_BASE_ADDR_MASK, MEM_BASE_ADDR_MASK, PCIE_CONFIG_SPACE_SIZE, REG_SIZE,
};
use pci::errors::Result as PciResult;
use pci::msix::{
@@ -41,7 +41,8 @@ use pci::msix::{
MSIX_TABLE_OFFSET, MSIX_TABLE_SIZE_MAX,
};
use pci::{
- le_read_u16, le_read_u32, le_write_u16, le_write_u32, ranges_overlap, PciBus, PciDevOps,
+ init_multifunction, le_read_u16, le_read_u32, le_write_u16, le_write_u32, ranges_overlap,
+ PciBus, PciDevOps,
};
use util::unix::host_page_size;
@@ -96,6 +97,8 @@ pub struct VfioPciDevice {
dev_id: Arc<AtomicU16>,
name: String,
parent_bus: Weak<Mutex<PciBus>>,
+ /// Multi-Function flag.
+ multi_func: bool,
}
impl VfioPciDevice {
@@ -106,6 +109,7 @@ impl VfioPciDevice {
devfn: u8,
name: String,
parent_bus: Weak<Mutex<PciBus>>,
+ multi_func: bool,
) -> Result<Self> {
Ok(VfioPciDevice {
// Unknown PCI or PCIe type here, allocate enough space to match the two types.
@@ -122,6 +126,7 @@ impl VfioPciDevice {
dev_id: Arc::new(AtomicU16::new(0)),
name,
parent_bus,
+ multi_func,
})
}
@@ -710,6 +715,15 @@ impl PciDevOps for VfioPciDevice {
PciResultExt::chain_err(self.pci_config_reset(), || {
"Failed to reset vfio device pci config space"
})?;
+ PciResultExt::chain_err(
+ init_multifunction(
+ self.multi_func,
+ &mut self.pci_config.config,
+ self.devfn,
+ self.parent_bus.clone(),
+ ),
+ || "Failed to init vfio device multifunction.",
+ )?;
#[cfg(target_arch = "aarch64")]
{
@@ -762,7 +776,15 @@ impl PciDevOps for VfioPciDevice {
return;
}
- if ranges_overlap(offset, end, BAR_0 as usize, BAR_5 as usize + REG_SIZE) {
+ // BAR and header_type are always controlled by StratoVirt.
+ if ranges_overlap(offset, end, BAR_0 as usize, (BAR_5 as usize) + REG_SIZE)
+ || ranges_overlap(
+ offset,
+ end,
+ HEADER_TYPE as usize,
+ (HEADER_TYPE as usize) + 2,
+ )
+ {
self.pci_config.read(offset, data);
return;
}
@@ -778,9 +800,6 @@ impl PciDevOps for VfioPciDevice {
if i + offset == 0x3d {
// Clear INIx
*data &= 0;
- } else if i + offset == 0x0e {
- // Clear multi-function
- *data &= 0x7f;
}
}
}
diff --git a/virtio/src/virtio_pci.rs b/virtio/src/virtio_pci.rs
index 8bdfce6..5a5b991 100644
--- a/virtio/src/virtio_pci.rs
+++ b/virtio/src/virtio_pci.rs
@@ -25,7 +25,10 @@ use pci::config::{
};
use pci::errors::{ErrorKind, Result as PciResult, ResultExt};
use pci::msix::update_dev_id;
-use pci::{config::PciConfig, init_msix, le_write_u16, ranges_overlap, PciBus, PciDevOps};
+use pci::{
+ config::PciConfig, init_msix, init_multifunction, le_write_u16, ranges_overlap, PciBus,
+ PciDevOps,
+};
use util::byte_code::ByteCode;
use vmm_sys_util::eventfd::EventFd;
@@ -487,6 +490,8 @@ pub struct VirtioPciDevice {
interrupt_cb: Option<Arc<VirtioInterrupt>>,
/// Virtio queues. The vector and Queue will be shared acrossing thread, so all with Arc<Mutex<..>> wrapper.
queues: Arc<Mutex<Vec<Arc<Mutex<Queue>>>>>,
+ /// Multi-Function flag.
+ multi_func: bool,
}
impl VirtioPciDevice {
@@ -496,6 +501,7 @@ impl VirtioPciDevice {
sys_mem: Arc<AddressSpace>,
device: Arc<Mutex<dyn VirtioDevice>>,
parent_bus: Weak<Mutex<PciBus>>,
+ multi_func: bool,
) -> Self {
let queue_num = device.lock().unwrap().queue_num();
let queue_size = device.lock().unwrap().queue_size();
@@ -515,6 +521,7 @@ impl VirtioPciDevice {
notify_eventfds: NotifyEventFds::new(queue_num),
interrupt_cb: None,
queues: Arc::new(Mutex::new(Vec::with_capacity(queue_num))),
+ multi_func,
}
}
@@ -869,6 +876,12 @@ impl PciDevOps for VirtioPciDevice {
SUBSYSTEM_ID,
0x40 + device_type as u16,
)?;
+ init_multifunction(
+ self.multi_func,
+ &mut self.config.config,
+ self.devfn,
+ self.parent_bus.clone(),
+ )?;
let common_cap = VirtioPciCap::new(
size_of::<VirtioPciCap>() as u8 + PCI_CAP_VNDR_AND_NEXT_SIZE,
@@ -1146,6 +1159,10 @@ mod tests {
use std::sync::{Arc, Mutex};
use address_space::{AddressSpace, GuestAddress, HostMemMapping};
+ use pci::{
+ config::{HEADER_TYPE, HEADER_TYPE_MULTIFUNC},
+ le_read_u16,
+ };
use util::num_ops::{read_u32, write_u32};
use vmm_sys_util::eventfd::EventFd;
@@ -1347,6 +1364,7 @@ mod tests {
sys_mem,
virtio_dev,
Arc::downgrade(&parent_bus),
+ false,
);
virtio_pci.init_write_mask().unwrap();
virtio_pci.init_write_clear_mask().unwrap();
@@ -1381,6 +1399,7 @@ mod tests {
sys_mem,
virtio_dev,
Arc::downgrade(&parent_bus),
+ false,
);
assert!(virtio_pci.realize().is_ok());
}
@@ -1414,6 +1433,7 @@ mod tests {
sys_mem,
virtio_dev,
Arc::downgrade(&parent_bus),
+ false,
);
// Prepare msix and interrupt callback
@@ -1467,4 +1487,35 @@ mod tests {
(common_cfg_ops.write)(0_u32.as_bytes(), GuestAddress(0), COMMON_STATUS_REG);
assert_eq!(virtio_pci.device_activated.load(Ordering::Relaxed), false);
}
+
+ #[test]
+ fn test_multifunction() {
+ let virtio_dev: Arc<Mutex<dyn VirtioDevice>> =
+ Arc::new(Mutex::new(VirtioDeviceTest::new()));
+ let sys_mem = AddressSpace::new(Region::init_container_region(u64::max_value())).unwrap();
+ let parent_bus = Arc::new(Mutex::new(PciBus::new(
+ String::from("test bus"),
+ #[cfg(target_arch = "x86_64")]
+ Region::init_container_region(1 << 16),
+ sys_mem.root().clone(),
+ )));
+ let mut virtio_pci = VirtioPciDevice::new(
+ String::from("test device"),
+ 24,
+ sys_mem,
+ virtio_dev,
+ Arc::downgrade(&parent_bus),
+ true,
+ );
+
+ assert!(init_multifunction(
+ virtio_pci.multi_func,
+ &mut virtio_pci.config.config,
+ virtio_pci.devfn,
+ virtio_pci.parent_bus.clone()
+ )
+ .is_ok());
+ let header_type = le_read_u16(&virtio_pci.config.config, HEADER_TYPE as usize).unwrap();
+ assert_eq!(header_type, HEADER_TYPE_MULTIFUNC as u16);
+ }
}
--
2.25.1

View File

@ -1,30 +0,0 @@
From d0d7be6b637db9e3d1401905472d15082b7f2de6 Mon Sep 17 00:00:00 2001
From: Ming Yang <yangming73@huawei.com>
Date: Tue, 24 Aug 2021 19:31:05 +0800
Subject: [PATCH 04/10] machine: fix more than one pcie-root-ports with same
id.
Signed-off-by: Ming Yang <yangming73@huawei.com>
---
machine/src/lib.rs | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/machine/src/lib.rs b/machine/src/lib.rs
index 8ba0ba3..22aed89 100644
--- a/machine/src/lib.rs
+++ b/machine/src/lib.rs
@@ -508,6 +508,11 @@ pub trait MachineOps {
let bdf = get_pci_bdf(cfg_args)?;
let (devfn, parent_bus) = self.get_devfn_and_parent_bus(&bdf)?;
let device_cfg = parse_root_port(cfg_args)?;
+ let pci_host = self.get_pci_host()?;
+ let bus = pci_host.lock().unwrap().root_bus.clone();
+ if PciBus::find_bus_by_name(&bus, &device_cfg.id).is_some() {
+ bail!("ID {} already exists.");
+ }
let rootport = RootPort::new(device_cfg.id, devfn, device_cfg.port, parent_bus);
rootport
.realize()
--
2.25.1

View File

@ -1,122 +0,0 @@
From 22362ed8a2d865e0b84bb20615eb1415086eb713 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Wed, 18 Aug 2021 11:18:45 +0800
Subject: [PATCH 4/8] machine/standard_vm: fix inappropriate file open
permissions
For PFlash device, code file is read-only and vars file is
readable and writable. So using right permissions to open
these two files.
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
---
machine/src/standard_vm/aarch64/mod.rs | 9 ++++-----
machine/src/standard_vm/mod.rs | 17 ++++++++++++++++-
machine/src/standard_vm/x86_64/mod.rs | 8 +++-----
3 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/machine/src/standard_vm/aarch64/mod.rs b/machine/src/standard_vm/aarch64/mod.rs
index 54c103c..d3c8670 100644
--- a/machine/src/standard_vm/aarch64/mod.rs
+++ b/machine/src/standard_vm/aarch64/mod.rs
@@ -44,9 +44,9 @@ use virtio::{qmp_balloon, qmp_query_balloon};
use vmm_sys_util::eventfd::EventFd;
use super::{AcpiBuilder, StdMachineOps};
-use crate::errors::Result as MachineResult;
use crate::errors::{ErrorKind, Result};
use crate::MachineOps;
+use crate::{errors::Result as MachineResult, standard_vm::open_pflash_file};
use pci_host_root::PciHostRoot;
use syscall::syscall_whitelist;
@@ -397,6 +397,7 @@ impl MachineOps for StdMachine {
/// Add pflash device.
fn add_pflash_device(&mut self, configs: &[PFlashConfig]) -> Result<()> {
+ use super::errors::ErrorKind as StdErrorKind;
use crate::errors::ResultExt;
let mut configs_vec = configs.to_vec();
@@ -407,10 +408,8 @@ impl MachineOps for StdMachine {
for i in 0..=1 {
let (fd, read_only) = if i < configs_vec.len() {
let config = &configs_vec[i];
- let fd = std::fs::OpenOptions::new()
- .read(true)
- .write(true)
- .open(config.path_on_host.clone())?;
+ let fd = open_pflash_file(&config.path_on_host, config.unit)
+ .chain_err(|| StdErrorKind::OpenFileErr(config.path_on_host.clone()))?;
(Some(fd), config.read_only)
} else {
(None, false)
diff --git a/machine/src/standard_vm/mod.rs b/machine/src/standard_vm/mod.rs
index 5ba7929..ff469c3 100644
--- a/machine/src/standard_vm/mod.rs
+++ b/machine/src/standard_vm/mod.rs
@@ -39,12 +39,15 @@ pub mod errors {
InitPCIeHostErr {
display("Failed to init PCIe host.")
}
+ OpenFileErr(path: String) {
+ display("Failed to open file: {}.", path)
+ }
}
}
}
-use std::mem::size_of;
use std::sync::{Arc, Mutex};
+use std::{fs::File, mem::size_of};
#[cfg(target_arch = "x86_64")]
use acpi::AcpiGenericAddress;
@@ -61,6 +64,18 @@ use aarch64::{LayoutEntryType, MEM_LAYOUT};
#[cfg(target_arch = "x86_64")]
use x86_64::{LayoutEntryType, MEM_LAYOUT};
+fn open_pflash_file(file_name: &str, unit: usize) -> Result<File> {
+ let fd = if unit == 0 {
+ std::fs::OpenOptions::new().read(true).open(file_name)?
+ } else {
+ std::fs::OpenOptions::new()
+ .read(true)
+ .write(true)
+ .open(file_name)?
+ };
+ Ok(fd)
+}
+
trait StdMachineOps: AcpiBuilder {
fn init_pci_host(&self) -> Result<()>;
diff --git a/machine/src/standard_vm/x86_64/mod.rs b/machine/src/standard_vm/x86_64/mod.rs
index 0cb2b63..1c29703 100644
--- a/machine/src/standard_vm/x86_64/mod.rs
+++ b/machine/src/standard_vm/x86_64/mod.rs
@@ -49,7 +49,7 @@ use vmm_sys_util::eventfd::EventFd;
use super::errors::{ErrorKind, Result};
use super::{AcpiBuilder, StdMachineOps};
use crate::errors::{ErrorKind as MachineErrorKind, Result as MachineResult};
-use crate::MachineOps;
+use crate::{standard_vm::open_pflash_file, MachineOps};
use mch::Mch;
use syscall::syscall_whitelist;
use util::byte_code::ByteCode;
@@ -398,10 +398,8 @@ impl MachineOps for StdMachine {
// of current PFlash device.
let mut flash_end: u64 = MEM_LAYOUT[LayoutEntryType::MemAbove4g as usize].0;
for config in configs_vec {
- let mut fd = std::fs::OpenOptions::new()
- .read(true)
- .write(true)
- .open(config.path_on_host.clone())?;
+ let mut fd = open_pflash_file(&config.path_on_host, config.unit)
+ .chain_err(|| ErrorKind::OpenFileErr(config.path_on_host.clone()))?;
let pfl_size = fd.metadata().unwrap().len();
if config.unit == 0 {
--
2.25.1

View File

@ -1,71 +0,0 @@
From aa94544a6fcc53039946cd6545893eed75d60d6e Mon Sep 17 00:00:00 2001
From: Ming Yang <yangming73@huawei.com>
Date: Tue, 24 Aug 2021 16:54:02 +0800
Subject: [PATCH 02/10] machine_manager: add autodeflate for balloon.
Signed-off-by: Ming Yang <yangming73@huawei.com>
---
machine_manager/src/machine.rs | 9 ++++++++-
machine_manager/src/qmp/mod.rs | 2 +-
machine_manager/src/qmp/qmp_schema.rs | 4 +++-
3 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/machine_manager/src/machine.rs b/machine_manager/src/machine.rs
index 49dbc38..ab8b288 100644
--- a/machine_manager/src/machine.rs
+++ b/machine_manager/src/machine.rs
@@ -299,13 +299,20 @@ pub trait DeviceInterface {
Response::create_response(serde_json::to_value(&vec_types).unwrap(), None)
}
- fn device_list_properties(&self) -> Response {
+ fn device_list_properties(&self, typename: String) -> Response {
let mut vec_props = Vec::<DeviceProps>::new();
let prop = DeviceProps {
name: "disable-legacy".to_string(),
prop_type: "OnOffAuto".to_string(),
};
vec_props.push(prop);
+ if typename.contains("virtio-balloon") {
+ let prop = DeviceProps {
+ name: "deflate-on-oom".to_string(),
+ prop_type: "bool".to_string(),
+ };
+ vec_props.push(prop);
+ }
Response::create_response(serde_json::to_value(&vec_props).unwrap(), None)
}
diff --git a/machine_manager/src/qmp/mod.rs b/machine_manager/src/qmp/mod.rs
index 8d9cd6f..f18f869 100644
--- a/machine_manager/src/qmp/mod.rs
+++ b/machine_manager/src/qmp/mod.rs
@@ -436,9 +436,9 @@ fn qmp_command_exec(
(query_cpus, query_cpus),
(query_balloon, query_balloon),
(list_type, list_type),
- (device_list_properties, device_list_properties),
(query_hotpluggable_cpus, query_hotpluggable_cpus);
(device_add, device_add, id, driver, addr, lun),
+ (device_list_properties, device_list_properties, typename),
(device_del, device_del, id),
(blockdev_add, blockdev_add, node_name, file, cache, read_only),
(netdev_add, netdev_add, id, if_name, fds),
diff --git a/machine_manager/src/qmp/qmp_schema.rs b/machine_manager/src/qmp/qmp_schema.rs
index 9544d46..a7c2a73 100644
--- a/machine_manager/src/qmp/qmp_schema.rs
+++ b/machine_manager/src/qmp/qmp_schema.rs
@@ -1375,7 +1375,9 @@ impl Command for list_type {
/// <- {"return":[]}
/// ```
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
-pub struct device_list_properties {}
+pub struct device_list_properties {
+ pub typename: String,
+}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct DeviceProps {
--
2.25.1

View File

@ -1,360 +0,0 @@
From b9ec3a6f3b7e35b342a778ded719cab4602e01a7 Mon Sep 17 00:00:00 2001
From: Ming Yang <yangming73@huawei.com>
Date: Sat, 28 Aug 2021 10:25:21 +0800
Subject: [PATCH 08/10] machine_manager: add multifunction for devices.
1. Add arugument: "multifunction" for devices
Signed-off-by: Xinle.Guo <guoxinle1@huawei.com>
Signed-off-by: Ming Yang <yangming73@huawei.com>
---
machine_manager/src/config/balloon.rs | 7 +++-
machine_manager/src/config/chardev.rs | 43 +++++++++++++++--------
machine_manager/src/config/drive.rs | 9 +++++
machine_manager/src/config/network.rs | 9 +++++
machine_manager/src/config/pci.rs | 49 +++++++++++++++++++++++++++
machine_manager/src/config/rng.rs | 8 +++++
machine_manager/src/config/vfio.rs | 8 ++++-
7 files changed, 116 insertions(+), 17 deletions(-)
diff --git a/machine_manager/src/config/balloon.rs b/machine_manager/src/config/balloon.rs
index 77dc1b5..ec19445 100644
--- a/machine_manager/src/config/balloon.rs
+++ b/machine_manager/src/config/balloon.rs
@@ -47,6 +47,7 @@ pub fn parse_balloon(vm_config: &mut VmConfig, balloon_config: &str) -> Result<B
.push("")
.push("bus")
.push("addr")
+ .push("multifunction")
.push("id")
.push("deflate-on-oom");
cmd_parser.parse(balloon_config)?;
@@ -84,7 +85,7 @@ mod tests {
}
#[test]
- fn test_pci_block_config_cmdline_parser() {
+ fn test_pci_balloon_config_cmdline_parser() {
let mut vm_config = VmConfig::default();
let bln_cfg = "virtio-balloon-pci,deflate-on-oom=true,bus=pcie.0,addr=0x1.0x2,id=balloon0";
let bln_cfg_res = parse_balloon(&mut vm_config, bln_cfg);
@@ -98,6 +99,10 @@ mod tests {
let pci = pci_bdf.unwrap();
assert_eq!(pci.bus, "pcie.0".to_string());
assert_eq!(pci.addr, (1, 2));
+
+ let mut vm_config = VmConfig::default();
+ let bln_cfg = "virtio-balloon-pci,deflate-on-oom=true,bus=pcie.0,addr=0x1.0x2,id=balloon0,multifunction=on";
+ assert!(parse_balloon(&mut vm_config, bln_cfg).is_ok());
}
#[test]
diff --git a/machine_manager/src/config/chardev.rs b/machine_manager/src/config/chardev.rs
index e5b3ff1..c1f37b5 100644
--- a/machine_manager/src/config/chardev.rs
+++ b/machine_manager/src/config/chardev.rs
@@ -16,7 +16,7 @@ use super::{
errors::{ErrorKind, Result, ResultExt},
get_pci_bdf, pci_args_check, PciBdf,
};
-use crate::config::{CmdParser, ConfigCheck, VmConfig};
+use crate::config::{CmdParser, ConfigCheck, ExBool, VmConfig};
const MAX_STRING_LENGTH: usize = 255;
const MAX_PATH_LENGTH: usize = 4096;
@@ -275,6 +275,7 @@ pub fn parse_vsock(vsock_config: &str) -> Result<VsockConfig> {
.push("id")
.push("bus")
.push("addr")
+ .push("multifunction")
.push("guest-cid")
.push("vhostfd");
cmd_parser.parse(vsock_config)?;
@@ -290,18 +291,7 @@ pub fn parse_vsock(vsock_config: &str) -> Result<VsockConfig> {
} else {
return Err(ErrorKind::FieldIsMissing("guest-cid", "vsock").into());
};
- let device_type = cmd_parser.get_value::<String>("")?;
- // Safe, because "parse_vsock" function only be called when certain
- // devices type are added.
- let dev_type = device_type.unwrap();
- if dev_type == *"vhost-vsock-device" {
- if cmd_parser.get_value::<String>("bus")?.is_some() {
- bail!("virtio mmio device does not support bus property");
- }
- if cmd_parser.get_value::<String>("addr")?.is_some() {
- bail!("virtio mmio device does not support addr property");
- }
- }
+
let vhost_fd = cmd_parser.get_value::<i32>("vhostfd")?;
let vsock = VsockConfig {
id,
@@ -315,6 +305,7 @@ pub fn parse_vsock(vsock_config: &str) -> Result<VsockConfig> {
pub struct VirtioSerialInfo {
pub id: String,
pub pci_bdf: Option<PciBdf>,
+ pub multifunction: bool,
}
impl ConfigCheck for VirtioSerialInfo {
@@ -333,7 +324,12 @@ impl ConfigCheck for VirtioSerialInfo {
pub fn parse_virtio_serial(vm_config: &mut VmConfig, serial_config: &str) -> Result<()> {
let mut cmd_parser = CmdParser::new("virtio-serial");
- cmd_parser.push("").push("id").push("bus").push("addr");
+ cmd_parser
+ .push("")
+ .push("id")
+ .push("bus")
+ .push("addr")
+ .push("multifunction");
cmd_parser.parse(serial_config)?;
pci_args_check(&cmd_parser)?;
@@ -343,14 +339,24 @@ pub fn parse_virtio_serial(vm_config: &mut VmConfig, serial_config: &str) -> Res
} else {
"".to_string()
};
+ let multifunction = if let Some(switch) = cmd_parser.get_value::<ExBool>("multifunction")? {
+ switch.into()
+ } else {
+ false
+ };
let virtio_serial = if serial_config.contains("-pci") {
let pci_bdf = get_pci_bdf(serial_config)?;
VirtioSerialInfo {
id,
pci_bdf: Some(pci_bdf),
+ multifunction,
}
} else {
- VirtioSerialInfo { id, pci_bdf: None }
+ VirtioSerialInfo {
+ id,
+ pci_bdf: None,
+ multifunction,
+ }
};
virtio_serial.check()?;
vm_config.virtio_serial = Some(virtio_serial);
@@ -434,6 +440,13 @@ mod tests {
console_cfg.chardev.backend,
ChardevType::Socket("/path/to/socket".to_string())
);
+
+ let mut vm_config = VmConfig::default();
+ assert!(parse_virtio_serial(
+ &mut vm_config,
+ "virtio-serial-pci,bus=pcie.0,addr=0x1.0x2,multifunction=on"
+ )
+ .is_ok());
}
#[test]
diff --git a/machine_manager/src/config/drive.rs b/machine_manager/src/config/drive.rs
index 3aaef75..16831df 100644
--- a/machine_manager/src/config/drive.rs
+++ b/machine_manager/src/config/drive.rs
@@ -164,6 +164,7 @@ pub fn parse_blk(vm_config: &mut VmConfig, drive_config: &str) -> Result<BlkDevC
.push("id")
.push("bus")
.push("addr")
+ .push("multifunction")
.push("drive")
.push("bootindex")
.push("serial")
@@ -412,6 +413,14 @@ mod tests {
// drive "rootfs" has been removed.
let blk_cfg_res = parse_blk(&mut vm_config, blk_cfg);
assert!(blk_cfg_res.is_err());
+
+ let mut vm_config = VmConfig::default();
+ assert!(vm_config
+ .add_drive("id=rootfs,file=/path/to/rootfs,serial=111111,readonly=off,direct=on")
+ .is_ok());
+ let blk_cfg =
+ "virtio-blk-pci,id=blk1,bus=pcie.0,addr=0x1.0x2,drive=rootfs,multifunction=on";
+ assert!(parse_blk(&mut vm_config, blk_cfg).is_ok());
}
#[test]
diff --git a/machine_manager/src/config/network.rs b/machine_manager/src/config/network.rs
index 71e6b3f..b0ad545 100644
--- a/machine_manager/src/config/network.rs
+++ b/machine_manager/src/config/network.rs
@@ -159,6 +159,7 @@ pub fn parse_net(vm_config: &mut VmConfig, net_config: &str) -> Result<NetworkIn
.push("netdev")
.push("bus")
.push("addr")
+ .push("multifunction")
.push("mac")
.push("iothread");
@@ -344,5 +345,13 @@ mod tests {
let net_cfg_res = parse_net(&mut vm_config, net_cfg);
assert!(net_cfg_res.is_err());
+
+ let mut vm_config = VmConfig::default();
+ assert!(vm_config
+ .add_netdev("tap,id=eth1,ifname=tap1,vhost=on,vhostfd=4")
+ .is_ok());
+ let net_cfg =
+ "virtio-net-pci,id=net1,netdev=eth1,bus=pcie.0,addr=0x1.0x2,mac=12:34:56:78:9A:BC,multifunction=on";
+ assert!(parse_net(&mut vm_config, net_cfg).is_ok());
}
}
diff --git a/machine_manager/src/config/pci.rs b/machine_manager/src/config/pci.rs
index 13bca99..a3a6c9d 100644
--- a/machine_manager/src/config/pci.rs
+++ b/machine_manager/src/config/pci.rs
@@ -12,6 +12,7 @@
use super::errors::{ErrorKind, Result, ResultExt};
use super::{CmdParser, ConfigCheck, MAX_STRING_LENGTH};
+use crate::config::ExBool;
/// Basic information of pci devices such as bus number,
/// slot number and function number.
@@ -43,6 +44,7 @@ impl Default for PciBdf {
pub struct RootPortConfig {
pub port: u8,
pub id: String,
+ pub multifunction: bool,
}
impl ConfigCheck for RootPortConfig {
@@ -64,6 +66,7 @@ impl Default for RootPortConfig {
RootPortConfig {
port: 0,
id: "".to_string(),
+ multifunction: false,
}
}
}
@@ -112,6 +115,21 @@ pub fn get_pci_bdf(pci_cfg: &str) -> Result<PciBdf> {
Ok(pci_bdf)
}
+pub fn get_multi_function(pci_cfg: &str) -> Result<bool> {
+ let mut cmd_parser = CmdParser::new("multifunction");
+ cmd_parser.push("").push("multifunction");
+ cmd_parser.get_parameters(pci_cfg)?;
+
+ if let Some(multi_func) = cmd_parser
+ .get_value::<ExBool>("multifunction")
+ .chain_err(|| "Failed to get multifunction parameter, please set on or off (default).")?
+ {
+ return Ok(multi_func.inner);
+ }
+
+ Ok(false)
+}
+
pub fn parse_root_port(rootport_cfg: &str) -> Result<RootPortConfig> {
let mut cmd_parser = CmdParser::new("pcie-root-port");
cmd_parser
@@ -138,6 +156,12 @@ pub fn parse_root_port(rootport_cfg: &str) -> Result<RootPortConfig> {
} else {
return Err(ErrorKind::FieldIsMissing("id", "rootport").into());
}
+ root_port.multifunction =
+ if let Some(multi_func) = cmd_parser.get_value::<ExBool>("multifunction")? {
+ multi_func.into()
+ } else {
+ false
+ };
root_port.check()?;
Ok(root_port)
@@ -155,6 +179,9 @@ pub fn pci_args_check(cmd_parser: &CmdParser) -> Result<()> {
if cmd_parser.get_value::<String>("addr")?.is_some() {
bail!("virtio mmio device does not support addr arguments");
}
+ if cmd_parser.get_value::<ExBool>("multifunction")?.is_some() {
+ bail!("virtio mmio device does not support multifunction arguments");
+ }
}
Ok(())
}
@@ -193,4 +220,26 @@ mod tests {
let pci_bdf = get_pci_bdf("virtio-balloon-device,addr=0x1.0x2");
assert!(pci_bdf.is_err());
}
+
+ #[test]
+ fn test_get_multi_function() {
+ assert_eq!(
+ get_multi_function("virtio-balloon-device,bus=pcie.0,addr=0x1.0x2").unwrap(),
+ false
+ );
+ assert_eq!(
+ get_multi_function("virtio-balloon-device,bus=pcie.0,addr=0x1.0x2,multifunction=on")
+ .unwrap(),
+ true
+ );
+ assert_eq!(
+ get_multi_function("virtio-balloon-device,bus=pcie.0,addr=0x1.0x2,multifunction=off")
+ .unwrap(),
+ false
+ );
+ assert!(get_multi_function(
+ "virtio-balloon-device,bus=pcie.0,addr=0x1.0x2,multifunction=close"
+ )
+ .is_err());
+ }
}
diff --git a/machine_manager/src/config/rng.rs b/machine_manager/src/config/rng.rs
index 295c6f2..139d15e 100644
--- a/machine_manager/src/config/rng.rs
+++ b/machine_manager/src/config/rng.rs
@@ -72,6 +72,7 @@ pub fn parse_rng_dev(vm_config: &mut VmConfig, rng_config: &str) -> Result<RngCo
.push("id")
.push("bus")
.push("addr")
+ .push("multifunction")
.push("max-bytes")
.push("period")
.push("rng");
@@ -234,5 +235,12 @@ mod tests {
let rng_cfg = "virtio-rng-device,rng=objrng0,bus=pcie.0,addr=0x1.0x3";
let rng_config = parse_rng_dev(&mut vm_config, rng_cfg);
assert!(rng_config.is_err());
+
+ let mut vm_config = VmConfig::default();
+ assert!(vm_config
+ .add_object("rng-random,id=objrng0,filename=/path/to/random_file")
+ .is_ok());
+ let rng_cfg = "virtio-rng-pci,rng=objrng0,bus=pcie.0,addr=0x1.0x3,multifunction=on";
+ assert!(parse_rng_dev(&mut vm_config, rng_cfg).is_ok());
}
}
diff --git a/machine_manager/src/config/vfio.rs b/machine_manager/src/config/vfio.rs
index 2a941c5..5f7d450 100644
--- a/machine_manager/src/config/vfio.rs
+++ b/machine_manager/src/config/vfio.rs
@@ -52,7 +52,8 @@ pub fn parse_vfio(_vm_config: &VmConfig, vfio_config: &str) -> Result<VfioConfig
.push("host")
.push("id")
.push("bus")
- .push("addr");
+ .push("addr")
+ .push("multifunction");
cmd_parser.parse(vfio_config)?;
let mut vfio: VfioConfig = VfioConfig::default();
@@ -127,5 +128,10 @@ mod tests {
let pci = pci_bdf.unwrap();
assert_eq!(pci.bus, "pcie.0".to_string());
assert_eq!(pci.addr, (1, 2));
+
+ let mut vm_config = VmConfig::default();
+ let vfio_cfg1 =
+ "vfio-pci,host=0000:1a:00.3,id=net,bus=pcie.0,addr=0x1.0x2,multifunction=on";
+ assert!(parse_vfio(&mut vm_config, vfio_cfg1).is_ok());
}
}
--
2.25.1

View File

@ -1,135 +0,0 @@
From a2dcc9cb71d8a341d5f437edcbe1a9c19a69e1a7 Mon Sep 17 00:00:00 2001
From: Ming Yang <yangming73@huawei.com>
Date: Fri, 27 Aug 2021 16:51:29 +0800
Subject: [PATCH 07/10] machine_manager: move argument "serial" from -drive to
-device virtio-blk-pci/device.
1. When interconnect with libvirt, the "serial" argument is given followed by -device
virtio-blk-pci. Thus it is moved in this commit.
Signed-off-by: Ming Yang <yangming73@huawei.com>
---
docs/config_guidebook.md | 8 ++++----
machine_manager/src/config/drive.rs | 25 +++++++++++++------------
2 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/docs/config_guidebook.md b/docs/config_guidebook.md
index e1279e1..b1f7b08 100644
--- a/docs/config_guidebook.md
+++ b/docs/config_guidebook.md
@@ -171,11 +171,11 @@ If you want to boot VM with a virtio block device as rootfs, you should add `roo
```shell
# virtio mmio block device.
--drive id=drive_id,file=path_on_host[,serial=serial_num,readonly=off,direct=off,throttling.iops-total=200]
--device virtio-blk-device,drive=drive_id[,iothread=iothread1]
+-drive id=drive_id,file=path_on_host[,readonly=off][,direct=off][,throttling.iops-total=200]
+-device virtio-blk-device,drive=drive_id[,iothread=iothread1][,serial=serial_num]
# virtio pci block device.
--drive id=drive_id,file=path_on_host[,serial=serial_num,readonly=off,direct=off,throttling.iops-total=200]
--device virtio-blk-pci,drive=drive_id,bus=pcie.0,addr=0x3.0x0[,iothread=iothread1]
+-drive id=drive_id,file=path_on_host[,readonly=off][,direct=off][,throttling.iops-total=200]
+-device virtio-blk-pci,drive=drive_id,bus=pcie.0,addr=0x3.0x0[,iothread=iothread1,][serial=serial_num]
```
diff --git a/machine_manager/src/config/drive.rs b/machine_manager/src/config/drive.rs
index 4d05eb8..3aaef75 100644
--- a/machine_manager/src/config/drive.rs
+++ b/machine_manager/src/config/drive.rs
@@ -62,7 +62,6 @@ pub struct DriveConfig {
pub path_on_host: String,
pub read_only: bool,
pub direct: bool,
- pub serial_num: Option<String>,
pub iops: Option<u64>,
}
@@ -73,7 +72,6 @@ impl Default for DriveConfig {
path_on_host: "".to_string(),
read_only: false,
direct: true,
- serial_num: None,
iops: None,
}
}
@@ -155,9 +153,6 @@ pub fn parse_drive(cmd_parser: CmdParser) -> Result<DriveConfig> {
if let Some(direct) = cmd_parser.get_value::<ExBool>("direct")? {
drive.direct = direct.into();
}
- if let Some(serial) = cmd_parser.get_value::<String>("serial")? {
- drive.serial_num = Some(serial);
- }
drive.iops = cmd_parser.get_value::<u64>("throttling.iops-total")?;
Ok(drive)
}
@@ -171,6 +166,7 @@ pub fn parse_blk(vm_config: &mut VmConfig, drive_config: &str) -> Result<BlkDevC
.push("addr")
.push("drive")
.push("bootindex")
+ .push("serial")
.push("iothread");
cmd_parser.parse(drive_config)?;
@@ -192,12 +188,15 @@ pub fn parse_blk(vm_config: &mut VmConfig, drive_config: &str) -> Result<BlkDevC
blkdevcfg.iothread = Some(iothread);
}
+ if let Some(serial) = cmd_parser.get_value::<String>("serial")? {
+ blkdevcfg.serial_num = Some(serial);
+ }
+
if let Some(drive_arg) = &vm_config.drives.remove(&blkdrive) {
blkdevcfg.id = drive_arg.id.clone();
blkdevcfg.path_on_host = drive_arg.path_on_host.clone();
blkdevcfg.read_only = drive_arg.read_only;
blkdevcfg.direct = drive_arg.direct;
- blkdevcfg.serial_num = drive_arg.serial_num.clone();
blkdevcfg.iops = drive_arg.iops;
} else {
bail!("No drive configured matched for blk device");
@@ -361,11 +360,13 @@ mod tests {
fn test_drive_config_cmdline_parser() {
let mut vm_config = VmConfig::default();
assert!(vm_config
- .add_drive("id=rootfs,file=/path/to/rootfs,serial=111111,readonly=off,direct=on,throttling.iops-total=200")
+ .add_drive(
+ "id=rootfs,file=/path/to/rootfs,readonly=off,direct=on,throttling.iops-total=200"
+ )
.is_ok());
let blk_cfg_res = parse_blk(
&mut vm_config,
- "virtio-blk-device,drive=rootfs,iothread=iothread1",
+ "virtio-blk-device,drive=rootfs,iothread=iothread1,serial=111111",
);
assert!(blk_cfg_res.is_ok());
let blk_device_config = blk_cfg_res.unwrap();
@@ -377,11 +378,11 @@ mod tests {
let mut vm_config = VmConfig::default();
assert!(vm_config
- .add_drive("id=rootfs,file=/path/to/rootfs,serial=111111,readonly=off,direct=on")
+ .add_drive("id=rootfs,file=/path/to/rootfs,readonly=off,direct=on")
.is_ok());
let blk_cfg_res = parse_blk(
&mut vm_config,
- "virtio-blk-device,drive=rootfs1,iothread=iothread1,iops=200",
+ "virtio-blk-device,drive=rootfs1,iothread=iothread1,iops=200,serial=111111",
);
assert!(blk_cfg_res.is_err()); // Can not find drive named "rootfs1".
}
@@ -390,9 +391,9 @@ mod tests {
fn test_pci_block_config_cmdline_parser() {
let mut vm_config = VmConfig::default();
assert!(vm_config
- .add_drive("id=rootfs,file=/path/to/rootfs,serial=111111,readonly=off,direct=on")
+ .add_drive("id=rootfs,file=/path/to/rootfs,readonly=off,direct=on")
.is_ok());
- let blk_cfg = "virtio-blk-pci,id=blk1,bus=pcie.0,addr=0x1.0x2,drive=rootfs";
+ let blk_cfg = "virtio-blk-pci,id=blk1,bus=pcie.0,addr=0x1.0x2,drive=rootfs,serial=111111";
let blk_cfg_res = parse_blk(&mut vm_config, blk_cfg);
assert!(blk_cfg_res.is_ok());
let drive_configs = blk_cfg_res.unwrap();
--
2.25.1

View File

@ -1,44 +0,0 @@
From aa0f9438a27ad4ae2086d49b70d72def2f9f9024 Mon Sep 17 00:00:00 2001
From: Wei Gao <gaowei66@huawei.com>
Date: Thu, 26 Aug 2021 10:50:43 +0800
Subject: [PATCH 03/10] migration: add dev_id into VirtioPciState when save and
restore device state.
After commit 94c7bfbeeacda20d488b7ad2ad4fa9293f5883b4, pci device's dev_id will be reallocated when device activated or reset. So it's necessary to save dev_id during migration.
Signed-off-by: Wei Gao <gaowei66@huawei.com>
---
virtio/src/virtio_pci.rs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/virtio/src/virtio_pci.rs b/virtio/src/virtio_pci.rs
index aaf009e..8bdfce6 100644
--- a/virtio/src/virtio_pci.rs
+++ b/virtio/src/virtio_pci.rs
@@ -439,6 +439,7 @@ impl Clone for NotifyEventFds {
#[desc_version(compat_version = "0.1.0")]
pub struct VirtioPciState {
activated: bool,
+ dev_id: u16,
/// Max length of config_space is 4096.
config_space: [u8; 4096],
write_mask: [u8; 4096],
@@ -1040,6 +1041,7 @@ impl StateTransfer for VirtioPciDevice {
// Save virtio pci state.
state.activated = self.device_activated.load(Ordering::Relaxed);
+ state.dev_id = self.dev_id.load(Ordering::Acquire);
{
let locked_queues = self.queues.lock().unwrap();
for (index, queue) in locked_queues.iter().enumerate() {
@@ -1083,6 +1085,7 @@ impl StateTransfer for VirtioPciDevice {
// Set virtio pci state.
self.device_activated
.store(pci_state.activated, Ordering::Relaxed);
+ self.dev_id.store(pci_state.dev_id, Ordering::Release);
{
let queue_type = self.common_config.lock().unwrap().queue_type;
let mut locked_queues = self.queues.lock().unwrap();
--
2.25.1

View File

@ -1,104 +0,0 @@
From 7c9db6a2e3082b41af3e62b241d49553f5bb8492 Mon Sep 17 00:00:00 2001
From: Wei Gao <gaowei66@huawei.com>
Date: Wed, 18 Aug 2021 14:30:08 +0800
Subject: [PATCH 2/8] migration: fix an error during migration interface on
aarch64.
Change the order of GICv3 device register to the end. Because it rely on
vcpu_init if boot with multi vcpu.
Signed-off-by: Wei Gao <gaowei66@huawei.com>
---
.../src/interrupt_controller/aarch64/gicv3.rs | 3 ++-
hypervisor/src/kvm/mod.rs | 1 +
machine/src/lib.rs | 2 +-
migration/src/manager.rs | 16 ++++++++++++----
4 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/devices/src/interrupt_controller/aarch64/gicv3.rs b/devices/src/interrupt_controller/aarch64/gicv3.rs
index 3303b32..6559e73 100644
--- a/devices/src/interrupt_controller/aarch64/gicv3.rs
+++ b/devices/src/interrupt_controller/aarch64/gicv3.rs
@@ -389,13 +389,14 @@ impl GICDevice for GICv3 {
gic_conf: &GICConfig,
) -> Result<Arc<dyn GICDevice + std::marker::Send + std::marker::Sync>> {
let gicv3 = Arc::new(GICv3::new(gic_conf)?);
- MigrationManager::register_device_instance(GICv3State::descriptor(), gicv3.clone());
if gicv3.its_dev.is_some() {
MigrationManager::register_device_instance(
GICv3ItsState::descriptor(),
gicv3.its_dev.as_ref().unwrap().clone(),
+ true,
);
}
+ MigrationManager::register_device_instance(GICv3State::descriptor(), gicv3.clone(), true);
Ok(gicv3)
}
diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs
index 5b5be94..19193db 100644
--- a/hypervisor/src/kvm/mod.rs
+++ b/hypervisor/src/kvm/mod.rs
@@ -60,6 +60,7 @@ impl KVMFds {
migration::MigrationManager::register_device_instance(
state::KvmDeviceState::descriptor(),
Arc::new(state::KvmDevice {}),
+ false,
);
kvm_fds
diff --git a/machine/src/lib.rs b/machine/src/lib.rs
index 8a095b3..9eb3039 100644
--- a/machine/src/lib.rs
+++ b/machine/src/lib.rs
@@ -233,7 +233,7 @@ pub trait MachineOps {
));
cpus.push(cpu.clone());
- MigrationManager::register_device_instance(cpu::ArchCPU::descriptor(), cpu);
+ MigrationManager::register_device_instance(cpu::ArchCPU::descriptor(), cpu, false);
}
if let Some(boot_config) = boot_cfg {
diff --git a/migration/src/manager.rs b/migration/src/manager.rs
index 480b59b..7ec4767 100644
--- a/migration/src/manager.rs
+++ b/migration/src/manager.rs
@@ -162,14 +162,22 @@ impl MigrationManager {
///
/// * `device_desc` - The `DeviceStateDesc` of device instance.
/// * `entry` - Device instance with migratable interface.
- pub fn register_device_instance<T>(device_desc: DeviceStateDesc, device_entry: Arc<T>)
- where
+ /// * `reverse` - Register device in order or in the reverse order.
+ pub fn register_device_instance<T>(
+ device_desc: DeviceStateDesc,
+ device_entry: Arc<T>,
+ reverse: bool,
+ ) where
T: MigrationHook + Sync + Send + 'static,
{
Self::register_device_desc(device_desc);
let entry = MigrationEntry::Safe(device_entry);
- let nr_entry = Self::entry_db_len();
+ let nr_entry = if reverse {
+ !0 - Self::entry_db_len()
+ } else {
+ Self::entry_db_len()
+ };
MIGRATION_MANAGER
.entry
@@ -333,7 +341,7 @@ mod tests {
let device_v2 = Arc::new(DeviceV2::default());
let device_v2_mutex = Arc::new(Mutex::new(DeviceV2::default()));
- MigrationManager::register_device_instance(DeviceV1State::descriptor(), device_v1);
+ MigrationManager::register_device_instance(DeviceV1State::descriptor(), device_v1, false);
MigrationManager::register_memory_instance(device_v2);
MigrationManager::register_device_instance_mutex(
DeviceV2State::descriptor(),
--
2.25.1

View File

@ -1,29 +0,0 @@
From 79a5a58e74e28c175ee836bda60090cf511f893d Mon Sep 17 00:00:00 2001
From: Wei Gao <gaowei66@huawei.com>
Date: Wed, 18 Aug 2021 15:30:33 +0800
Subject: [PATCH 3/8] migration: fix an errors during the PL011 device state
restore.
This bug is leaded by commit d24f510cf271f144084266ff292db7e94c004b53.
Add the function to register device again.
Signed-off-by: Wei Gao <gaowei66@huawei.com>
---
devices/src/legacy/pl011.rs | 1 +
1 file changed, 1 insertion(+)
diff --git a/devices/src/legacy/pl011.rs b/devices/src/legacy/pl011.rs
index 133487e..65bf64b 100644
--- a/devices/src/legacy/pl011.rs
+++ b/devices/src/legacy/pl011.rs
@@ -172,6 +172,7 @@ impl PL011 {
param_type: "earlycon".to_string(),
value: format!("pl011,mmio,0x{:08x}", region_base),
});
+ MigrationManager::register_device_instance_mutex(PL011State::descriptor(), dev.clone());
let locked_dev = dev.lock().unwrap();
locked_dev.chardev.lock().unwrap().set_input_callback(&dev);
EventLoop::update_event(
--
2.25.1

View File

@ -1,66 +0,0 @@
From c44049602c22c09b82ae5ca67afc2fa202d4fbf1 Mon Sep 17 00:00:00 2001
From: Wei Gao <gaowei66@huawei.com>
Date: Thu, 26 Aug 2021 11:59:02 +0800
Subject: [PATCH 05/10] migration: move function "transport_reset" to save
state stage for vhost_vsock device.
Because of vsock control protocol is not resilient to vsock packed loss, vsock device will
break the connection during restoring. As a solution to this, send a "VIRTIO_VSOCK_EVENT_TRANSPORT_RESET"
event when VM doing snapshot. Then vsock pack will not loss. More details about this event can be
found in virtio Spec section 5.10.6.6.
Signed-off-by: Wei Gao <gaowei66@huawei.com>
---
virtio/src/vhost/kernel/vsock.rs | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/virtio/src/vhost/kernel/vsock.rs b/virtio/src/vhost/kernel/vsock.rs
index 5c3d198..29e59af 100644
--- a/virtio/src/vhost/kernel/vsock.rs
+++ b/virtio/src/vhost/kernel/vsock.rs
@@ -113,7 +113,7 @@ impl Vsock {
/// The `VIRTIO_VSOCK_EVENT_TRANSPORT_RESET` event indicates that communication has
/// been interrupted. The driver shuts down established connections and the guest_cid
/// configuration field is fetched again.
- fn transport_reset(&mut self) -> Result<()> {
+ fn transport_reset(&self) -> Result<()> {
let mut event_queue_locked = self.event_queue.as_ref().unwrap().lock().unwrap();
let element = event_queue_locked
.vring
@@ -136,7 +136,7 @@ impl Vsock {
.chain_err(|| format!("Failed to add used ring {}", element.index))?;
if let Some(interrupt_cb) = &self.interrupt_cb {
- interrupt_cb(&VirtioInterruptType::Vring, None)
+ interrupt_cb(&VirtioInterruptType::Vring, Some(&*event_queue_locked))
.chain_err(|| ErrorKind::EventFdWrite)?;
}
@@ -337,6 +337,9 @@ impl StateTransfer for Vsock {
self.backend.as_ref().unwrap().set_running(true),
|| "Failed to set vsock backend running",
)?;
+ migration::errors::ResultExt::chain_err(self.transport_reset(), || {
+ "Failed to send vsock transport reset event"
+ })?;
Ok(state.as_bytes().to_vec())
}
@@ -358,10 +361,11 @@ impl StateTransfer for Vsock {
}
impl MigrationHook for Vsock {
+ #[cfg(target_arch = "aarch64")]
fn resume(&mut self) -> migration::errors::Result<()> {
- if let Err(e) = self.transport_reset() {
- error!("Failed to resume virtio vsock device: {}", e);
- }
+ migration::errors::ResultExt::chain_err(self.transport_reset(), || {
+ "Failed to resume virtio vsock device"
+ })?;
Ok(())
}
--
2.25.1

View File

@ -5,33 +5,14 @@
%define _unpackaged_files_terminate_build 0
Name: stratovirt
Version: 2.0.0
Release: 6
Version: 2.1.0
Release: 1
Summary: StratoVirt is an opensource VMM(Virtual Machine Manager) which aims to perform next generation virtualization.
License: Mulan PSL v2
URL: https://gitee.com/openeuler/StratoVirt
Source0: %{name}-%{version}.tar.gz
Patch001: fix-spelling-errors-in-project.patch
Patch002: migration-fix-an-error-during-migration-interface-on.patch
Patch003: migration-fix-an-errors-during-the-PL011-device-stat.patch
Patch004: machine-standard_vm-fix-inappropriate-file-open-perm.patch
Patch005: kernel_config-update-kernel-config-5.10-on-aarch64-p.patch
Patch006: syscall-add-syscall-newfstatat-in-x86_64-unknown-lin.patch
Patch007: vfio-fix-the-problem-of-dma-mapping-failed.patch
Patch008: virtio-fix-dev_id-initialization-for-virtio-pci-and-.patch
Patch009: docs-fix-some-statement.patch
Patch010: machine_manager-add-autodeflate-for-balloon.patch
Patch011: migration-add-dev_id-into-VirtioPciState-when-save-a.patch
Patch012: machine-fix-more-than-one-pcie-root-ports-with-same-.patch
Patch013: migration-move-function-transport_reset-to-save-stat.patch
Patch014: vfio-adding-ram-device-region-to-vfio-bar-region.patch
Patch015: machine_manager-move-argument-serial-from-drive-to-d.patch
Patch016: machine_manager-add-multifunction-for-devices.patch
Patch017: machine-add-init_multifunction-function-to-init-mult.patch
Patch018: machine-add-realization-for-multifunction.patch
ExclusiveArch: x86_64 aarch64
%ifarch aarch64
@ -85,6 +66,18 @@ chmod 555 ${RPM_BUILD_ROOT}/usr/bin/stratovirt
chmod 555 ${RPM_BUILD_ROOT}/usr/bin/ozone
%changelog
* Fri Feb 11 2022 Jie Yang <yangjieyj.yang@huawei.com> - 2.1.0-1
- Add support for PCIe native hotplugging.
- Reduce memory consumption of reading edk2 firmware files on aarch64.
- Add support for booting from disk image directly.
- Add support for VM reboot and VM shutdown.
- Add support for guest memory preallocation.
- Add more test cases.
- Add and fix documentation.
- Replace lazy_static crate with once_cell.
- Performance enhancement for virtio-blk and virtio-net devices.
- Add ftrace support.
* Mon Aug 30 2021 Jie Yang <yangjieyj.yang@huawei.com> - 2.0.0-6
- docs: fix some statement
- machine_manager: add autodeflate for balloon

View File

@ -1,99 +0,0 @@
From 2a70e217561e64f460e95d4d89d145fc615f12ec Mon Sep 17 00:00:00 2001
From: Qi Xi <xiqi1@huawei.com>
Date: Fri, 20 Aug 2021 15:43:00 +0800
Subject: [PATCH 6/8] syscall: add syscall "newfstatat" in
x86_64-unknown-linux-gnu target
When we run stratovirt, built with GNU toolchain on x86 platform, and
use serial port for IO, it will be blocked. The bug is caused by when
it is the first time for rtc device to call "libc::gmtime_r" after
seccomp taking effect, it will use the syscall "newfstatat" which is
not in the syscall whitelist.
The bug is fixed by adding "newfstatat" to syscall whitelist with
x86_64-unknown-linux-gnu target.
Signed-off-by: Qi Xi <xiqi1@huawei.com>
---
docs/config_guidebook.md | 18 +++++++++++++++---
machine/src/micro_vm/syscall.rs | 4 +++-
machine/src/standard_vm/x86_64/syscall.rs | 4 +++-
3 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/docs/config_guidebook.md b/docs/config_guidebook.md
index 6a5cda7..72b4c7e 100644
--- a/docs/config_guidebook.md
+++ b/docs/config_guidebook.md
@@ -679,10 +679,22 @@ And you can also restore StratoVirt's **pid number** to a file by:
### 4.2 Seccomp
StratoVirt use [seccomp(2)](https://man7.org/linux/man-pages/man2/seccomp.2.html) to limit the syscalls
-in StratoVirt process by default. StratoVirt use only 40 syscalls in x86_64 (39 syscalls in aarch64) after running.
-It will make a slight influence on performance to StratoVirt. If you want to disable seccomp, you can
-run StratoVirt with `-disable-seccomp`.
+in StratoVirt process by default. It will make a slight influence on performance to StratoVirt.
+* X86_64
+| Number of Syscalls | GNU Toolchain | MUSL Toolchain |
+| :----------------: | :-----------: | :------------: |
+| Micro_vm | 41 | 41 |
+| Standard_vm | 46 | 43 |
+
+* AArch64
+
+| Number of Syscalls | GNU Toolchain | MUSL Toolchain |
+| :----------------: | :-----------: | :------------: |
+| Micro_vm | 39 | 40 |
+| Standard_vm | 43 | 42 |
+
+If you want to disable seccomp, you can run StratoVirt with `-disable-seccomp`.
```shell
# cmdline
-disable-seccomp
diff --git a/machine/src/micro_vm/syscall.rs b/machine/src/micro_vm/syscall.rs
index eb52df6..ddc9023 100644
--- a/machine/src/micro_vm/syscall.rs
+++ b/machine/src/micro_vm/syscall.rs
@@ -92,7 +92,7 @@ ioctl_iowr_nr!(KVM_GET_REG_LIST, KVMIO, 0xb0, kvm_reg_list);
///
/// # Notes
/// This allowlist limit syscall with:
-/// * x86_64-unknown-gnu: 40 syscalls
+/// * x86_64-unknown-gnu: 41 syscalls
/// * x86_64-unknown-musl: 41 syscalls
/// * aarch64-unknown-gnu: 39 syscalls
/// * aarch64-unknown-musl: 40 syscalls
@@ -153,6 +153,8 @@ pub fn syscall_whitelist() -> Vec<BpfRule> {
BpfRule::new(libc::SYS_statx),
#[cfg(all(target_env = "musl", target_arch = "x86_64"))]
BpfRule::new(libc::SYS_stat),
+ #[cfg(all(target_env = "gnu", target_arch = "x86_64"))]
+ BpfRule::new(libc::SYS_newfstatat),
#[cfg(all(target_env = "musl", target_arch = "aarch64"))]
BpfRule::new(libc::SYS_newfstatat),
#[cfg(target_arch = "x86_64")]
diff --git a/machine/src/standard_vm/x86_64/syscall.rs b/machine/src/standard_vm/x86_64/syscall.rs
index d794c78..dddeb8a 100644
--- a/machine/src/standard_vm/x86_64/syscall.rs
+++ b/machine/src/standard_vm/x86_64/syscall.rs
@@ -78,7 +78,7 @@ ioctl_iowr_nr!(KVM_GET_MSRS, KVMIO, 0x88, kvm_msrs);
///
/// # Notes
/// This allowlist limit syscall with:
-/// * x86_64-unknown-gnu: 45 syscalls
+/// * x86_64-unknown-gnu: 46 syscalls
/// * x86_64-unknown-musl: 43 syscalls
/// To reduce performance losses, the syscall rules is ordered by frequency.
pub fn syscall_whitelist() -> Vec<BpfRule> {
@@ -132,6 +132,8 @@ pub fn syscall_whitelist() -> Vec<BpfRule> {
BpfRule::new(libc::SYS_gettid),
BpfRule::new(libc::SYS_getpid),
BpfRule::new(libc::SYS_fstat),
+ #[cfg(all(target_env = "gnu"))]
+ BpfRule::new(libc::SYS_newfstatat),
BpfRule::new(libc::SYS_pread64),
BpfRule::new(libc::SYS_pwrite64),
BpfRule::new(libc::SYS_statx),
--
2.25.1

View File

@ -1,130 +0,0 @@
From 7d40dbe810cf21added24d7cf2425a62bae4b25b Mon Sep 17 00:00:00 2001
From: "Xinle.Guo" <guoxinle1@huawei.com>
Date: Tue, 24 Aug 2021 15:29:08 +0800
Subject: [PATCH 06/10] vfio: adding ram device region to vfio bar region
The ram device region was added to memory region of parent bus.
But vfio bar region could not manage ram device region when
adding or deleting sub region. To fix this problem, it should be
added as sub region of vfio bar region. The VM exits when
guest tries to read/write device bar region. Using ram device
region which remaps mmio region can improve I/O performance. So,
the memory region should look like as follows:
|----- IO region ----------|
|-----|---- IO region ----|-----|------|-ram device region-|(memory region)
virtio bar region vfio bar region
So, guest can read/write host device bar region directly.
Signed-off-by: Xinle.Guo <guoxinle1@huawei.com>
---
vfio/src/lib.rs | 4 ++--
vfio/src/vfio_pci.rs | 35 ++++++++++++++++++++---------------
2 files changed, 22 insertions(+), 17 deletions(-)
diff --git a/vfio/src/lib.rs b/vfio/src/lib.rs
index be70f45..801b7d0 100644
--- a/vfio/src/lib.rs
+++ b/vfio/src/lib.rs
@@ -23,8 +23,8 @@ pub mod errors {
PciErr(pci::errors::Error, pci::errors::ErrorKind);
}
errors {
- UnregMemBar(id: usize) {
- display("Failed to unmap BAR {} in memory space.", id)
+ AddRegBar(id: usize) {
+ display("Failed to add sub region at the BAR {} in memory space.", id)
}
VfioIoctl(ioctl: String, result: i32) {
display("Vfio ioctl failed: {}, result is: {}", ioctl, result)
diff --git a/vfio/src/vfio_pci.rs b/vfio/src/vfio_pci.rs
index b42e321..e366e47 100644
--- a/vfio/src/vfio_pci.rs
+++ b/vfio/src/vfio_pci.rs
@@ -345,19 +345,19 @@ impl VfioPciDevice {
.chain_err(|| "Failed to get vfio bar info")?;
let size = vfio_bar.size;
+ let region = Region::init_container_region(size);
let bar_region = if i == table_bar {
- let region = Region::init_container_region(size);
region
.add_subregion(
Region::init_io_region(table_size as u64, table_ops.clone()),
table_offset,
)
- .chain_err(|| ErrorKind::UnregMemBar(i as usize))?;
+ .chain_err(|| ErrorKind::AddRegBar(i as usize))?;
if table_offset > 0 {
region
.add_subregion(Region::init_io_region(table_offset, bar_ops.clone()), 0)
- .chain_err(|| ErrorKind::UnregMemBar(i as usize))?;
+ .chain_err(|| ErrorKind::AddRegBar(i as usize))?;
}
if table_offset + table_size < size {
@@ -369,11 +369,14 @@ impl VfioPciDevice {
),
table_offset + table_size,
)
- .chain_err(|| ErrorKind::UnregMemBar(i as usize))?;
+ .chain_err(|| ErrorKind::AddRegBar(i as usize))?;
}
region
} else {
- Region::init_io_region(size, bar_ops.clone())
+ region
+ .add_subregion(Region::init_io_region(size, bar_ops.clone()), 0)
+ .chain_err(|| ErrorKind::AddRegBar(i as usize))?;
+ region
};
self.pci_config
@@ -634,14 +637,16 @@ impl VfioPciDevice {
.chain_err(|| "Failed to create HostMemMapping")?;
let ram_device = Region::init_ram_device_region(Arc::new(host_mmap));
- // Avoid being covered by user memory region.
- ram_device.set_priority(1);
- let parent_bus = self.parent_bus.upgrade().unwrap();
- let locked_parent_bus = parent_bus.lock().unwrap();
- locked_parent_bus
- .mem_region
- .add_subregion(ram_device, gpa + mmap.offset)
- .chain_err(|| "Failed add to mem region")?;
+ let bar = self
+ .pci_config
+ .bars
+ .get_mut(i as usize)
+ .chain_err(|| "Failed to get pci bar info")?;
+ bar.region
+ .as_ref()
+ .unwrap()
+ .add_subregion(ram_device, mmap.offset)
+ .chain_err(|| ErrorKind::AddRegBar(i as usize))?;
}
}
Ok(())
@@ -757,7 +762,7 @@ impl PciDevOps for VfioPciDevice {
return;
}
- if offset >= (BAR_0 as usize) && offset < (BAR_5 as usize) + REG_SIZE {
+ if ranges_overlap(offset, end, BAR_0 as usize, BAR_5 as usize + REG_SIZE) {
self.pci_config.read(offset, data);
return;
}
@@ -806,7 +811,7 @@ impl PciDevOps for VfioPciDevice {
cap_offset = msix.lock().unwrap().msix_cap_offset as usize;
}
- if ranges_overlap(offset, end, COMMAND as usize, COMMAND as usize + 4) {
+ if ranges_overlap(offset, end, COMMAND as usize, COMMAND as usize + REG_SIZE) {
self.pci_config
.write(offset, data, self.dev_id.load(Ordering::Acquire));
--
2.25.1

View File

@ -1,228 +0,0 @@
From 023dde42b55a58c7a41293566e95a0fc94efa2c6 Mon Sep 17 00:00:00 2001
From: "Xinle.Guo" <guoxinle1@huawei.com>
Date: Thu, 19 Aug 2021 20:48:25 +0800
Subject: [PATCH 7/8] vfio: fix the problem of dma mapping failed
Failed to use libvirt to manager more than two vfio devices.
The reason is that creating a container for every vfio device,
the process stratovirt uses more than the memory locked limit.
Signed-off-by: Xinle.Guo <guoxinle1@huawei.com>
---
machine/src/lib.rs | 24 +++++++++++-------------
vfio/src/vfio_dev.rs | 25 +++++++++++++++----------
vfio/src/vfio_pci.rs | 31 ++++++++++++++++++-------------
3 files changed, 44 insertions(+), 36 deletions(-)
diff --git a/machine/src/lib.rs b/machine/src/lib.rs
index 9eb3039..8ba0ba3 100644
--- a/machine/src/lib.rs
+++ b/machine/src/lib.rs
@@ -121,7 +121,7 @@ use devices::legacy::FwCfgOps;
#[cfg(target_arch = "aarch64")]
use devices::InterruptController;
use hypervisor::KVM_FDS;
-use kvm_ioctls::{DeviceFd, VcpuFd};
+use kvm_ioctls::VcpuFd;
use machine_manager::config::{
get_pci_bdf, parse_balloon, parse_blk, parse_net, parse_rng_dev, parse_root_port, parse_vfio,
parse_virtconsole, parse_virtio_serial, parse_vsock, MachineMemConfig, PFlashConfig, PciBdf,
@@ -132,7 +132,7 @@ use machine_manager::machine::{KvmVmState, MachineInterface};
use migration::MigrationManager;
use util::loop_context::{EventNotifier, NotifierCallback, NotifierOperation};
use util::seccomp::{BpfRule, SeccompOpt, SyscallFilter};
-use vfio::vfio_pci::create_vfio_device;
+use vfio::vfio_pci::create_vfio_container;
use vfio::{VfioContainer, VfioPciDevice};
use virtio::{balloon_allow_list, Balloon, Block, Console, Rng, VirtioMmioDevice, VirtioPciDevice};
use vmm_sys_util::epoll::EventSet;
@@ -478,13 +478,8 @@ pub trait MachineOps {
&mut self,
vm_config: &VmConfig,
cfg_args: &str,
- dev_fd: Arc<DeviceFd>,
+ container: Arc<VfioContainer>,
) -> Result<()> {
- let sys_mem = self.get_sys_mem().clone();
- let container = Arc::new(
- VfioContainer::new(dev_fd, &sys_mem).chain_err(|| "Failed to create vfio container")?,
- );
-
let device_cfg: VfioConfig = parse_vfio(vm_config, cfg_args)?;
let path = "/sys/bus/pci/devices/".to_string() + &device_cfg.host;
let name = device_cfg.id;
@@ -543,10 +538,7 @@ pub trait MachineOps {
.chain_err(|| ErrorKind::AddDevErr("pflash".to_string()))?;
}
- // Create an emulated kvm device that is used for VFIO. It should be created only once.
- // See the kernel docs for `KVM_CREATE_DEVICE` to get more info.
- let vfio_dev = create_vfio_device().chain_err(|| "Failed to create kvm device for VFIO")?;
-
+ let mut container: Option<Arc<VfioContainer>> = None;
for dev in &cloned_vm_config.devices {
let cfg_args = dev.1.as_str();
match dev.0.as_str() {
@@ -581,7 +573,13 @@ pub trait MachineOps {
self.add_virtio_rng(vm_config, cfg_args)?;
}
"vfio-pci" => {
- self.add_vfio_device(&vm_config, cfg_args, vfio_dev.clone())?;
+ if container.is_none() {
+ container = Some(
+ create_vfio_container(self.get_sys_mem().clone())
+ .chain_err(|| "Failed to create vfio container")?,
+ );
+ }
+ self.add_vfio_device(&vm_config, cfg_args, container.clone().unwrap())?;
}
_ => {
bail!("Unsupported device: {:?}", dev.0.as_str());
diff --git a/vfio/src/vfio_dev.rs b/vfio/src/vfio_dev.rs
index 30f7d5a..93922ba 100644
--- a/vfio/src/vfio_dev.rs
+++ b/vfio/src/vfio_dev.rs
@@ -96,8 +96,8 @@ pub struct VfioMemoryRegion {
pub memory_size: u64,
// Host virtual address.
pub userspace_addr: u64,
- // No flags specified for now.
- flags_padding: u64,
+ // IOMMU mapped flag.
+ pub iommu_mapped: bool,
}
/// `VfioMemInfo` structure contains pinning pages information. If any pages need to be zapped from
@@ -131,7 +131,7 @@ impl VfioMemInfo {
guest_phys_addr,
memory_size,
userspace_addr,
- flags_padding: 0_u64,
+ iommu_mapped: false,
});
Ok(())
@@ -150,7 +150,7 @@ impl VfioMemInfo {
guest_phys_addr: fr.addr_range.base.raw_value(),
memory_size: fr.addr_range.size,
userspace_addr: hva + fr.offset_in_region,
- flags_padding: 0_u64,
+ iommu_mapped: false,
};
let mut mem_regions = self.regions.lock().unwrap();
for (index, mr) in mem_regions.iter().enumerate() {
@@ -378,9 +378,11 @@ impl VfioGroup {
return Err(ErrorKind::VfioIoctl("VFIO_GROUP_SET_CONTAINER".to_string(), ret).into());
}
- if let Err(e) = container.set_iommu(vfio::VFIO_TYPE1v2_IOMMU) {
- unsafe { ioctl_with_ref(&self.group, VFIO_GROUP_UNSET_CONTAINER(), &raw_fd) };
- return Err(e).chain_err(|| "Failed to set IOMMU");
+ if container.groups.lock().unwrap().is_empty() {
+ if let Err(e) = container.set_iommu(vfio::VFIO_TYPE1v2_IOMMU) {
+ unsafe { ioctl_with_ref(&self.group, VFIO_GROUP_UNSET_CONTAINER(), &raw_fd) };
+ return Err(e).chain_err(|| "Failed to set IOMMU");
+ }
}
if let Err(e) = container.kvm_device_add_group(&self.group.as_raw_fd()) {
@@ -473,15 +475,18 @@ impl VfioDevice {
group_id = n.parse::<u32>().chain_err(|| "Invalid iommu group id")?;
}
- let mut groups = container.groups.lock().unwrap();
- if let Some(g) = groups.get(&group_id) {
+ if let Some(g) = container.groups.lock().unwrap().get(&group_id) {
return Ok(g.clone());
}
let group = Arc::new(VfioGroup::new(group_id)?);
group
.connect_container(&container)
.chain_err(|| "Fail to connect container")?;
- groups.insert(group_id, group.clone());
+ container
+ .groups
+ .lock()
+ .unwrap()
+ .insert(group_id, group.clone());
Ok(group)
}
diff --git a/vfio/src/vfio_pci.rs b/vfio/src/vfio_pci.rs
index 5cc674a..7bec445 100644
--- a/vfio/src/vfio_pci.rs
+++ b/vfio/src/vfio_pci.rs
@@ -19,13 +19,12 @@ use std::sync::{Arc, Mutex, Weak};
use byteorder::{ByteOrder, LittleEndian};
use error_chain::ChainedError;
use kvm_bindings::{kvm_create_device, kvm_device_type_KVM_DEV_TYPE_VFIO};
-use kvm_ioctls::DeviceFd;
use vfio_bindings::bindings::vfio;
use vmm_sys_util::eventfd::EventFd;
use vmm_sys_util::ioctl::ioctl_with_mut_ref;
use super::errors::{ErrorKind, Result, ResultExt};
-use address_space::{FileBackend, GuestAddress, HostMemMapping, Region, RegionOps};
+use address_space::{AddressSpace, FileBackend, GuestAddress, HostMemMapping, Region, RegionOps};
use hypervisor::{MsiVector, KVM_FDS};
#[cfg(target_arch = "aarch64")]
use pci::config::SECONDARY_BUS_NUM;
@@ -380,7 +379,7 @@ impl VfioPciDevice {
.register_bar(i as usize, bar_region, vfio_bar.region_type, false, size);
}
- self.map_guest_memory()?;
+ self.do_dma_map()?;
Ok(())
}
@@ -569,14 +568,17 @@ impl VfioPciDevice {
}
/// Add all guest memory regions into IOMMU table.
- fn map_guest_memory(&mut self) -> Result<()> {
+ fn do_dma_map(&mut self) -> Result<()> {
let container = &self.vfio_device.container;
- let regions = container.vfio_mem_info.regions.lock().unwrap();
-
- for r in regions.iter() {
- container
- .vfio_dma_map(r.guest_phys_addr, r.memory_size, r.userspace_addr)
- .chain_err(|| "Failed to add guest memory region map into IOMMU table")?;
+ let mut regions = container.vfio_mem_info.regions.lock().unwrap();
+
+ for r in regions.iter_mut() {
+ if !r.iommu_mapped {
+ container
+ .vfio_dma_map(r.guest_phys_addr, r.memory_size, r.userspace_addr)
+ .chain_err(|| "Failed to add guest memory region map into IOMMU table")?;
+ r.iommu_mapped = true;
+ }
}
Ok(())
}
@@ -872,7 +874,7 @@ fn get_irq_rawfds(gsi_msi_routes: &[GsiMsiRoute]) -> Vec<RawFd> {
rawfds
}
-pub fn create_vfio_device() -> Result<Arc<DeviceFd>> {
+pub fn create_vfio_container(sys_mem: Arc<AddressSpace>) -> Result<Arc<VfioContainer>> {
let mut vfio_device = kvm_create_device {
type_: kvm_device_type_KVM_DEV_TYPE_VFIO,
fd: 0,
@@ -884,7 +886,10 @@ pub fn create_vfio_device() -> Result<Arc<DeviceFd>> {
.as_ref()
.unwrap()
.create_device(&mut vfio_device)
- .chain_err(|| "Failed to create VFIO type KVM device")?;
+ .chain_err(|| "Failed to create kvm device for VFIO")?;
- Ok(Arc::new(dev_fd))
+ Ok(Arc::new(
+ VfioContainer::new(Arc::new(dev_fd), &sys_mem)
+ .chain_err(|| "Failed to create vfio container")?,
+ ))
}
--
2.25.1

View File

@ -1,614 +0,0 @@
From 4ba032f8967c660b8eafb3adaf9b44b95474c7c3 Mon Sep 17 00:00:00 2001
From: Ming Yang <yangming73@huawei.com>
Date: Wed, 11 Aug 2021 14:52:26 +0800
Subject: [PATCH 8/8] virtio: fix dev_id initialization for virtio-pci and vfio
device on aarch64 platform
On aarch64 platform, dev_id information is necessary for virtio-pci device
to send msix.
This commit fixes the dev_id initialization in virtio_pci transport module,
and set dev_id information according to the number of bus where the device
is attached to.
Signed-off-by: Ming Yang <yangming73@huawei.com>
---
pci/src/config.rs | 2 +
pci/src/msix.rs | 63 ++++++++++++++------
pci/src/root_port.rs | 10 +---
vfio/src/vfio_pci.rs | 34 +++++++----
virtio/src/virtio_pci.rs | 123 ++++++++++++++++++++++++---------------
5 files changed, 150 insertions(+), 82 deletions(-)
diff --git a/pci/src/config.rs b/pci/src/config.rs
index d7bd348..873fe7a 100644
--- a/pci/src/config.rs
+++ b/pci/src/config.rs
@@ -221,6 +221,7 @@ pub enum RegionType {
}
/// Registered bar.
+#[derive(Clone)]
pub struct Bar {
region_type: RegionType,
address: u64,
@@ -266,6 +267,7 @@ pub enum PcieDevType {
}
/// Configuration space of PCI/PCIe device.
+#[derive(Clone)]
pub struct PciConfig {
/// Configuration space data.
pub config: Vec<u8>,
diff --git a/pci/src/msix.rs b/pci/src/msix.rs
index 2831af4..5c04575 100644
--- a/pci/src/msix.rs
+++ b/pci/src/msix.rs
@@ -10,16 +10,19 @@
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
-use std::sync::{Arc, Mutex};
+use std::sync::atomic::{AtomicU16, Ordering};
+use std::sync::{Arc, Mutex, Weak};
use address_space::{GuestAddress, Region, RegionOps};
use hypervisor::{MsiVector, KVM_FDS};
use migration::{DeviceStateDesc, FieldDesc, MigrationHook, MigrationManager, StateTransfer};
use util::{byte_code::ByteCode, num_ops::round_up};
-use crate::config::{CapId, PciConfig, RegionType};
+use crate::config::{CapId, PciConfig, RegionType, SECONDARY_BUS_NUM};
use crate::errors::{Result, ResultExt};
-use crate::{le_read_u16, le_read_u32, le_read_u64, le_write_u16, le_write_u32, le_write_u64};
+use crate::{
+ le_read_u16, le_read_u32, le_read_u64, le_write_u16, le_write_u32, le_write_u64, PciBus,
+};
pub const MSIX_TABLE_ENTRY_SIZE: u16 = 16;
pub const MSIX_TABLE_SIZE_MAX: u16 = 0x7ff;
@@ -71,7 +74,7 @@ pub struct Msix {
pub func_masked: bool,
pub enabled: bool,
pub msix_cap_offset: u16,
- pub dev_id: u16,
+ pub dev_id: Arc<AtomicU16>,
}
impl Msix {
@@ -90,7 +93,7 @@ impl Msix {
func_masked: true,
enabled: true,
msix_cap_offset,
- dev_id,
+ dev_id: Arc::new(AtomicU16::new(dev_id)),
};
msix.mask_all_vectors();
msix
@@ -148,7 +151,11 @@ impl Msix {
le_write_u64(&mut self.pba, offset, old_val & pending_bit).unwrap();
}
- fn register_memory_region(msix: Arc<Mutex<Self>>, region: &Region, dev_id: u16) -> Result<()> {
+ fn register_memory_region(
+ msix: Arc<Mutex<Self>>,
+ region: &Region,
+ dev_id: Arc<AtomicU16>,
+ ) -> Result<()> {
let locked_msix = msix.lock().unwrap();
let table_size = locked_msix.table.len() as u64;
let pba_size = locked_msix.pba.len() as u64;
@@ -170,7 +177,7 @@ impl Msix {
let is_masked: bool = locked_msix.is_vector_masked(vector);
if was_masked && !is_masked {
locked_msix.clear_pending_vector(vector);
- locked_msix.notify(vector, dev_id);
+ locked_msix.notify(vector, dev_id.load(Ordering::Acquire));
}
true
@@ -264,7 +271,7 @@ impl StateTransfer for Msix {
state.func_masked = self.func_masked;
state.enabled = self.enabled;
state.msix_cap_offset = self.msix_cap_offset;
- state.dev_id = self.dev_id;
+ state.dev_id = self.dev_id.load(Ordering::Acquire);
Ok(state.as_bytes().to_vec())
}
@@ -280,7 +287,7 @@ impl StateTransfer for Msix {
self.func_masked = msix_state.func_masked;
self.enabled = msix_state.enabled;
self.msix_cap_offset = msix_state.msix_cap_offset;
- self.dev_id = msix_state.dev_id;
+ self.dev_id = Arc::new(AtomicU16::new(msix_state.dev_id));
Ok(())
}
@@ -318,7 +325,7 @@ impl MigrationHook for Msix {
msg_data: msg.data,
masked: false,
#[cfg(target_arch = "aarch64")]
- dev_id: self.dev_id as u32,
+ dev_id: self.dev_id.load(Ordering::Acquire) as u32,
};
if let Err(e) = locked_irq_table.add_msi_route(allocated_gsi, msi_vector) {
bail!("Failed to add msi route to global irq routing table: {}", e);
@@ -330,7 +337,7 @@ impl MigrationHook for Msix {
if self.is_vector_pending(vector) {
self.clear_pending_vector(vector);
- send_msix(msg, self.dev_id);
+ send_msix(msg, self.dev_id.load(Ordering::Acquire));
}
}
}
@@ -377,7 +384,12 @@ fn send_msix(msg: Message, dev_id: u16) {
}
/// MSI-X initialization.
-pub fn init_msix(bar_id: usize, vector_nr: u32, config: &mut PciConfig, dev_id: u16) -> Result<()> {
+pub fn init_msix(
+ bar_id: usize,
+ vector_nr: u32,
+ config: &mut PciConfig,
+ dev_id: Arc<AtomicU16>,
+) -> Result<()> {
if vector_nr > MSIX_TABLE_SIZE_MAX as u32 + 1 {
bail!("Too many msix vectors.");
}
@@ -401,7 +413,7 @@ pub fn init_msix(bar_id: usize, vector_nr: u32, config: &mut PciConfig, dev_id:
table_size,
pba_size,
msix_cap_offset as u16,
- dev_id,
+ dev_id.load(Ordering::Acquire),
)));
let bar_size = ((table_size + pba_size) as u64).next_power_of_two();
let region = Region::init_container_region(bar_size);
@@ -415,6 +427,17 @@ pub fn init_msix(bar_id: usize, vector_nr: u32, config: &mut PciConfig, dev_id:
Ok(())
}
+pub fn update_dev_id(parent_bus: &Weak<Mutex<PciBus>>, devfn: u8, dev_id: &Arc<AtomicU16>) {
+ let bus_num = parent_bus
+ .upgrade()
+ .unwrap()
+ .lock()
+ .unwrap()
+ .number(SECONDARY_BUS_NUM as usize);
+ let device_id = ((bus_num as u16) << 8) | (devfn as u16);
+ dev_id.store(device_id, Ordering::Release);
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -425,9 +448,15 @@ mod tests {
let mut pci_config = PciConfig::new(PCI_CONFIG_SPACE_SIZE, 2);
// Too many vectors.
- assert!(init_msix(0, MSIX_TABLE_SIZE_MAX as u32 + 2, &mut pci_config, 0).is_err());
-
- init_msix(1, 2, &mut pci_config, 0).unwrap();
+ assert!(init_msix(
+ 0,
+ MSIX_TABLE_SIZE_MAX as u32 + 2,
+ &mut pci_config,
+ Arc::new(AtomicU16::new(0))
+ )
+ .is_err());
+
+ init_msix(1, 2, &mut pci_config, Arc::new(AtomicU16::new(0))).unwrap();
let msix_cap_start = 64_u8;
assert_eq!(pci_config.last_cap_end, 64 + MSIX_CAP_SIZE as u16);
// Capabilities pointer
@@ -492,7 +521,7 @@ mod tests {
#[test]
fn test_write_config() {
let mut pci_config = PciConfig::new(PCI_CONFIG_SPACE_SIZE, 2);
- init_msix(0, 2, &mut pci_config, 0).unwrap();
+ init_msix(0, 2, &mut pci_config, Arc::new(AtomicU16::new(0))).unwrap();
let msix = pci_config.msix.as_ref().unwrap();
let mut locked_msix = msix.lock().unwrap();
locked_msix.enabled = false;
diff --git a/pci/src/root_port.rs b/pci/src/root_port.rs
index ba1b5f7..948e31d 100644
--- a/pci/src/root_port.rs
+++ b/pci/src/root_port.rs
@@ -10,6 +10,7 @@
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
+use std::sync::atomic::AtomicU16;
use std::sync::{Arc, Mutex, Weak};
use address_space::Region;
@@ -117,13 +118,8 @@ impl PciDevOps for RootPort {
config_space[PREF_MEMORY_LIMIT as usize] = PREF_MEM_RANGE_64BIT;
self.config
.add_pcie_cap(self.devfn, self.port_num, PcieDevType::RootPort as u8)?;
- #[cfg(target_arch = "aarch64")]
- {
- self.dev_id = self.set_dev_id(0, self.devfn);
- init_msix(0, 1, &mut self.config, self.dev_id)?;
- }
- #[cfg(target_arch = "x86_64")]
- init_msix(0, 1, &mut self.config, 0)?;
+
+ init_msix(0, 1, &mut self.config, Arc::new(AtomicU16::new(0)))?;
let parent_bus = self.parent_bus.upgrade().unwrap();
let mut locked_parent_bus = parent_bus.lock().unwrap();
diff --git a/vfio/src/vfio_pci.rs b/vfio/src/vfio_pci.rs
index 5cc674a..640ff20 100644
--- a/vfio/src/vfio_pci.rs
+++ b/vfio/src/vfio_pci.rs
@@ -14,6 +14,7 @@ use std::collections::HashMap;
use std::mem::size_of;
use std::os::unix::io::{AsRawFd, RawFd};
use std::path::Path;
+use std::sync::atomic::{AtomicU16, Ordering};
use std::sync::{Arc, Mutex, Weak};
use byteorder::{ByteOrder, LittleEndian};
@@ -36,9 +37,9 @@ use pci::config::{
};
use pci::errors::Result as PciResult;
use pci::msix::{
- is_msix_enabled, Msix, MSIX_CAP_CONTROL, MSIX_CAP_ENABLE, MSIX_CAP_FUNC_MASK, MSIX_CAP_ID,
- MSIX_CAP_SIZE, MSIX_CAP_TABLE, MSIX_TABLE_BIR, MSIX_TABLE_ENTRY_SIZE, MSIX_TABLE_OFFSET,
- MSIX_TABLE_SIZE_MAX,
+ is_msix_enabled, update_dev_id, Msix, MSIX_CAP_CONTROL, MSIX_CAP_ENABLE, MSIX_CAP_FUNC_MASK,
+ MSIX_CAP_ID, MSIX_CAP_SIZE, MSIX_CAP_TABLE, MSIX_TABLE_BIR, MSIX_TABLE_ENTRY_SIZE,
+ MSIX_TABLE_OFFSET, MSIX_TABLE_SIZE_MAX,
};
use pci::{
le_read_u16, le_read_u32, le_write_u16, le_write_u32, ranges_overlap, PciBus, PciDevOps,
@@ -93,7 +94,7 @@ pub struct VfioPciDevice {
// Maintains a list of GSI with irqfds that are registered to kvm.
gsi_msi_routes: Arc<Mutex<Vec<GsiMsiRoute>>>,
devfn: u8,
- dev_id: u16,
+ dev_id: Arc<AtomicU16>,
name: String,
parent_bus: Weak<Mutex<PciBus>>,
}
@@ -119,7 +120,7 @@ impl VfioPciDevice {
vfio_bars: Arc::new(Mutex::new(Vec::with_capacity(PCI_NUM_BARS as usize))),
gsi_msi_routes: Arc::new(Mutex::new(Vec::new())),
devfn,
- dev_id: 0,
+ dev_id: Arc::new(AtomicU16::new(0)),
name,
parent_bus,
})
@@ -404,7 +405,7 @@ impl VfioPciDevice {
table_size,
table_size / 128,
cap_offset as u16,
- self.dev_id,
+ self.dev_id.load(Ordering::Acquire),
)));
self.pci_config.msix = Some(msix.clone());
@@ -418,6 +419,9 @@ impl VfioPciDevice {
let cloned_dev = self.vfio_device.clone();
let cloned_gsi_routes = self.gsi_msi_routes.clone();
+ let parent_bus = self.parent_bus.clone();
+ let dev_id = self.dev_id.clone();
+ let devfn = self.devfn;
let write = move |data: &[u8], _: GuestAddress, offset: u64| -> bool {
let mut locked_msix = msix.lock().unwrap();
locked_msix.table[offset as usize..(offset as usize + data.len())]
@@ -429,13 +433,15 @@ impl VfioPciDevice {
}
let entry = locked_msix.get_message(vector as u16);
+
+ update_dev_id(&parent_bus, devfn, &dev_id);
let msix_vector = MsiVector {
msg_addr_lo: entry.address_lo,
msg_addr_hi: entry.address_hi,
msg_data: entry.data,
masked: false,
#[cfg(target_arch = "aarch64")]
- dev_id: locked_msix.dev_id as u32,
+ dev_id: dev_id.load(Ordering::Acquire) as u32,
};
let mut locked_gsi_routes = cloned_gsi_routes.lock().unwrap();
@@ -707,7 +713,7 @@ impl PciDevOps for VfioPciDevice {
.lock()
.unwrap()
.number(SECONDARY_BUS_NUM as usize);
- self.dev_id = self.set_dev_id(bus_num, self.devfn);
+ self.dev_id = Arc::new(AtomicU16::new(self.set_dev_id(bus_num, self.devfn)));
}
self.msix_info = Some(PciResultExt::chain_err(self.get_msix_info(), || {
@@ -799,7 +805,8 @@ impl PciDevOps for VfioPciDevice {
}
if ranges_overlap(offset, end, COMMAND as usize, COMMAND as usize + 4) {
- self.pci_config.write(offset, data, self.dev_id);
+ self.pci_config
+ .write(offset, data, self.dev_id.load(Ordering::Acquire));
if le_read_u32(&self.pci_config.config, offset).unwrap() & COMMAND_MEMORY_SPACE as u32
!= 0
@@ -822,7 +829,8 @@ impl PciDevOps for VfioPciDevice {
}
}
} else if ranges_overlap(offset, end, BAR_0 as usize, (BAR_5 as usize) + REG_SIZE) {
- self.pci_config.write(offset, data, self.dev_id);
+ self.pci_config
+ .write(offset, data, self.dev_id.load(Ordering::Acquire));
if size == 4 && LittleEndian::read_u32(data) != 0xffff_ffff {
let parent_bus = self.parent_bus.upgrade().unwrap();
@@ -838,7 +846,8 @@ impl PciDevOps for VfioPciDevice {
}
} else if ranges_overlap(offset, end, cap_offset, cap_offset + MSIX_CAP_SIZE as usize) {
let was_enable = is_msix_enabled(cap_offset, &self.pci_config.config);
- self.pci_config.write(offset, data, self.dev_id);
+ self.pci_config
+ .write(offset, data, self.dev_id.load(Ordering::Acquire));
let is_enable = is_msix_enabled(cap_offset, &self.pci_config.config);
if !was_enable && is_enable {
@@ -853,7 +862,8 @@ impl PciDevOps for VfioPciDevice {
}
}
} else {
- self.pci_config.write(offset, data, self.dev_id);
+ self.pci_config
+ .write(offset, data, self.dev_id.load(Ordering::Acquire));
}
}
diff --git a/virtio/src/virtio_pci.rs b/virtio/src/virtio_pci.rs
index 03645dc..aaf009e 100644
--- a/virtio/src/virtio_pci.rs
+++ b/virtio/src/virtio_pci.rs
@@ -24,6 +24,7 @@ use pci::config::{
VENDOR_ID,
};
use pci::errors::{ErrorKind, Result as PciResult, ResultExt};
+use pci::msix::update_dev_id;
use pci::{config::PciConfig, init_msix, le_write_u16, ranges_overlap, PciBus, PciDevOps};
use util::byte_code::ByteCode;
use vmm_sys_util::eventfd::EventFd;
@@ -459,13 +460,14 @@ pub struct VirtioPciState {
}
/// Virtio-PCI device structure
+#[derive(Clone)]
pub struct VirtioPciDevice {
/// Name of this device
name: String,
/// The entity of virtio device
device: Arc<Mutex<dyn VirtioDevice>>,
/// Device id
- dev_id: u16,
+ dev_id: Arc<AtomicU16>,
/// Devfn
devfn: u8,
/// If this device is activated or not.
@@ -500,7 +502,7 @@ impl VirtioPciDevice {
VirtioPciDevice {
name,
device,
- dev_id: 0_u16,
+ dev_id: Arc::new(AtomicU16::new(0)),
devfn,
device_activated: Arc::new(AtomicBool::new(false)),
sys_mem,
@@ -518,7 +520,7 @@ impl VirtioPciDevice {
fn assign_interrupt_cb(&mut self) {
let cloned_common_cfg = self.common_config.clone();
let cloned_msix = self.config.msix.clone();
- let dev_id = self.dev_id;
+ let dev_id = self.dev_id.clone();
let cb = Arc::new(Box::new(
move |int_type: &VirtioInterruptType, queue: Option<&Queue>| {
let vector = match int_type {
@@ -533,7 +535,9 @@ impl VirtioPciDevice {
};
if let Some(msix) = &cloned_msix {
- msix.lock().unwrap().notify(vector, dev_id);
+ msix.lock()
+ .unwrap()
+ .notify(vector, dev_id.load(Ordering::Acquire));
} else {
bail!("Failed to send interrupt, msix does not exist");
}
@@ -618,14 +622,7 @@ impl VirtioPciDevice {
true
};
- let cloned_virtio_dev = self.device.clone();
- let cloned_common_cfg = self.common_config.clone();
- let cloned_virtio_queue = self.queues.clone();
- let cloned_activated_flag = self.device_activated.clone();
- let cloned_notify_evts = self.notify_eventfds.clone();
- let cloned_sys_mem = self.sys_mem.clone();
- let cloned_int_cb = self.interrupt_cb.clone();
- let cloned_msix = self.config.msix.as_ref().unwrap().clone();
+ let cloned_pci_device = self.clone();
let common_write = move |data: &[u8], _addr: GuestAddress, offset: u64| -> bool {
let value = match data.len() {
1 => data[0] as u32,
@@ -639,13 +636,18 @@ impl VirtioPciDevice {
return false;
}
};
- let old_dev_status = cloned_common_cfg.lock().unwrap().device_status;
+ let old_dev_status = cloned_pci_device
+ .common_config
+ .lock()
+ .unwrap()
+ .device_status;
- if let Err(e) = cloned_common_cfg.lock().unwrap().write_common_config(
- &cloned_virtio_dev,
- offset,
- value,
- ) {
+ if let Err(e) = cloned_pci_device
+ .common_config
+ .lock()
+ .unwrap()
+ .write_common_config(&cloned_pci_device.device.clone(), offset, value)
+ {
error!(
"Failed to read common config of virtio-pci device, error is {}",
e.display_chain(),
@@ -653,21 +655,29 @@ impl VirtioPciDevice {
return false;
}
- if !cloned_activated_flag.load(Ordering::Acquire)
- && cloned_common_cfg.lock().unwrap().check_device_status(
- CONFIG_STATUS_ACKNOWLEDGE
- | CONFIG_STATUS_DRIVER
- | CONFIG_STATUS_DRIVER_OK
- | CONFIG_STATUS_FEATURES_OK,
- CONFIG_STATUS_FAILED,
- )
+ if !cloned_pci_device.device_activated.load(Ordering::Acquire)
+ && cloned_pci_device
+ .common_config
+ .lock()
+ .unwrap()
+ .check_device_status(
+ CONFIG_STATUS_ACKNOWLEDGE
+ | CONFIG_STATUS_DRIVER
+ | CONFIG_STATUS_DRIVER_OK
+ | CONFIG_STATUS_FEATURES_OK,
+ CONFIG_STATUS_FAILED,
+ )
{
- let queue_type = cloned_common_cfg.lock().unwrap().queue_type;
- let queues_config = &cloned_common_cfg.lock().unwrap().queues_config;
- let mut locked_queues = cloned_virtio_queue.lock().unwrap();
+ let queue_type = cloned_pci_device.common_config.lock().unwrap().queue_type;
+ let queues_config = &cloned_pci_device
+ .common_config
+ .lock()
+ .unwrap()
+ .queues_config;
+ let mut locked_queues = cloned_pci_device.queues.lock().unwrap();
for q_config in queues_config.iter() {
let queue = Queue::new(*q_config, queue_type).unwrap();
- if !queue.is_valid(&cloned_sys_mem) {
+ if !queue.is_valid(&cloned_pci_device.sys_mem) {
error!("Failed to activate device: Invalid queue");
return false;
}
@@ -675,10 +685,10 @@ impl VirtioPciDevice {
locked_queues.push(arc_queue.clone());
}
- let queue_evts = cloned_notify_evts.clone().events;
- if let Some(cb) = cloned_int_cb.clone() {
- if let Err(e) = cloned_virtio_dev.lock().unwrap().activate(
- cloned_sys_mem.clone(),
+ let queue_evts = cloned_pci_device.notify_eventfds.clone().events;
+ if let Some(cb) = cloned_pci_device.interrupt_cb.clone() {
+ if let Err(e) = cloned_pci_device.device.lock().unwrap().activate(
+ cloned_pci_device.sys_mem.clone(),
cb,
&locked_queues,
queue_evts,
@@ -689,20 +699,43 @@ impl VirtioPciDevice {
error!("Failed to activate device: No interrupt callback");
return false;
}
- cloned_activated_flag.store(true, Ordering::Release);
+ cloned_pci_device
+ .device_activated
+ .store(true, Ordering::Release);
+
+ update_dev_id(
+ &cloned_pci_device.parent_bus,
+ cloned_pci_device.devfn,
+ &cloned_pci_device.dev_id,
+ );
}
- if old_dev_status != 0 && cloned_common_cfg.lock().unwrap().device_status == 0 {
- let mut locked_queues = cloned_virtio_queue.lock().unwrap();
+ if old_dev_status != 0
+ && cloned_pci_device
+ .common_config
+ .lock()
+ .unwrap()
+ .device_status
+ == 0
+ {
+ let mut locked_queues = cloned_pci_device.queues.lock().unwrap();
locked_queues.clear();
- cloned_activated_flag.store(false, Ordering::Release);
+ cloned_pci_device
+ .device_activated
+ .store(false, Ordering::Release);
+ let cloned_msix = cloned_pci_device.config.msix.as_ref().unwrap().clone();
cloned_msix.lock().unwrap().reset();
- if let Err(e) = cloned_virtio_dev.lock().unwrap().reset() {
+ if let Err(e) = cloned_pci_device.device.lock().unwrap().reset() {
error!(
"Failed to reset virtio device, error is {}",
e.display_chain()
);
}
+ update_dev_id(
+ &cloned_pci_device.parent_bus,
+ cloned_pci_device.devfn,
+ &cloned_pci_device.dev_id,
+ );
}
true
@@ -874,15 +907,12 @@ impl PciDevOps for VirtioPciDevice {
self.modern_mem_region_map(notify_cap)?;
let nvectors = self.device.lock().unwrap().queue_num() + 1;
- #[cfg(target_arch = "aarch64")]
- {
- self.dev_id = self.set_dev_id(0, self.devfn);
- }
+
init_msix(
VIRTIO_PCI_MSIX_BAR_IDX as usize,
nvectors as u32,
&mut self.config,
- self.dev_id,
+ self.dev_id.clone(),
)?;
self.assign_interrupt_cb();
@@ -950,7 +980,8 @@ impl PciDevOps for VirtioPciDevice {
return;
}
- self.config.write(offset, data, self.dev_id);
+ self.config
+ .write(offset, data, self.dev_id.clone().load(Ordering::Acquire));
if ranges_overlap(
offset,
end,
@@ -1388,7 +1419,7 @@ mod tests {
VIRTIO_PCI_MSIX_BAR_IDX as usize,
virtio_pci.device.lock().unwrap().queue_num() as u32 + 1,
&mut virtio_pci.config,
- virtio_pci.dev_id,
+ virtio_pci.dev_id.clone(),
)
.unwrap();
// Prepare valid queue config
--
2.25.1