mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
Compare commits
228 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ed8e01faf | ||
|
|
1a5c6631a5 | ||
|
|
acec7e34fc | ||
|
|
deca570544 | ||
|
|
7cfb2139d0 | ||
|
|
1a7a76511f | ||
|
|
8a22b2987f | ||
|
|
1eb8a4671f | ||
|
|
2fe3586eba | ||
|
|
805cb303d5 | ||
|
|
97307a7fc1 | ||
|
|
6ed1f83a87 | ||
|
|
04aff2e2f9 | ||
|
|
0268089ac6 | ||
|
|
5d5d338e10 | ||
|
|
8f1404eeef | ||
|
|
9dba097224 | ||
|
|
ce5c5833cb | ||
|
|
3cb2b72e92 | ||
|
|
88fda7c305 | ||
|
|
b8b5dccfd8 | ||
|
|
6880692a78 | ||
|
|
76911fbeb4 | ||
|
|
0eb245e177 | ||
|
|
c866ccb3a1 | ||
|
|
bb68e0bc3b | ||
|
|
f81f4490b0 | ||
|
|
c419d3286b | ||
|
|
d76743ed0b | ||
|
|
1e2aa769e5 | ||
|
|
8091c28dd5 | ||
|
|
eca1df4e2d | ||
|
|
3d8728488d | ||
|
|
650cbce017 | ||
|
|
058946772a | ||
|
|
b443900cc2 | ||
|
|
8fad60bada | ||
|
|
2e8a552c24 | ||
|
|
7c917c0e74 | ||
|
|
aee54fc8f3 | ||
|
|
e10e1f6eed | ||
|
|
0ccb597baf | ||
|
|
a3cbc1ff72 | ||
|
|
e7cf513064 | ||
|
|
3dc15a9259 | ||
|
|
bcee2fbd2d | ||
|
|
1b87f332b0 | ||
|
|
7839e121f6 | ||
|
|
2c4fa258a6 | ||
|
|
0e0159db0c | ||
|
|
b5bcdbaf48 | ||
|
|
c7b794a7c5 | ||
|
|
280bef834b | ||
|
|
df92495e31 | ||
|
|
e62aafdf58 | ||
|
|
a14c70019a | ||
|
|
48c8649891 | ||
|
|
b4eb015d86 | ||
|
|
3e00247a47 | ||
|
|
6bce7f7937 | ||
|
|
f3d3d8daed | ||
|
|
dcddfbff91 | ||
|
|
787426d4e6 | ||
|
|
c357adae44 | ||
|
|
9f5325fd52 | ||
|
|
7f3fa39d81 | ||
|
|
9a5f3fc2a7 | ||
|
|
7932cd22ca | ||
|
|
195eba188a | ||
|
|
9341cce8b3 | ||
|
|
2ac7232288 | ||
|
|
905135fe8c | ||
|
|
57f532a760 | ||
|
|
831dff8b4e | ||
|
|
4db7530f28 | ||
|
|
239e2adc68 | ||
|
|
1c60591eab | ||
|
|
5e53bbf405 | ||
|
|
fbaceea4c0 | ||
|
|
56ec5ca260 | ||
|
|
3ffd2cb9be | ||
|
|
cacec04df6 | ||
|
|
72ec98b8a8 | ||
|
|
a174ad011e | ||
|
|
e9cc23ea94 | ||
|
|
6c245f6cf1 | ||
|
|
dd92715ed2 | ||
|
|
b3d1278838 | ||
|
|
92c2101f7c | ||
|
|
ff46fb69d0 | ||
|
|
efc583c13e | ||
|
|
d882f8c928 | ||
|
|
213da7d862 | ||
|
|
9c5528490e | ||
|
|
7bfb51489b | ||
|
|
e1ef141112 | ||
|
|
5f27d649a6 | ||
|
|
cab103d172 | ||
|
|
084fdd9d10 | ||
|
|
74c064e477 | ||
|
|
14f27e4219 | ||
|
|
9a8ff68bc1 | ||
|
|
b461200211 | ||
|
|
aba2513322 | ||
|
|
cb8fc4dc9f | ||
|
|
47be87c7cc | ||
|
|
66d52199a7 | ||
|
|
f840327ffb | ||
|
|
719e36049b | ||
|
|
f583f993ee | ||
|
|
bcb1dfb86f | ||
|
|
d7a69f8aa1 | ||
|
|
f36b5f3e3c | ||
|
|
cdaa4d3ad7 | ||
|
|
8c73af048a | ||
|
|
e2121c5d75 | ||
|
|
9a7199a116 | ||
|
|
c549bbd72a | ||
|
|
c39d43dee1 | ||
|
|
b76e0b358f | ||
|
|
9bc309b416 | ||
|
|
65a39f43cb | ||
|
|
324c924ca4 | ||
|
|
75ad89670b | ||
|
|
d4f01bdb43 | ||
|
|
e1c9a956da | ||
|
|
c2137e33a0 | ||
|
|
c05010887f | ||
|
|
334aa8c941 | ||
|
|
5d2df70a79 | ||
|
|
af88ff1c49 | ||
|
|
40dc3e7c10 | ||
|
|
56b9149325 | ||
|
|
7ae631e0c1 | ||
|
|
84454f142d | ||
|
|
a335cbb8d5 | ||
|
|
0cf9218d3f | ||
|
|
2439625785 | ||
|
|
01e2826f26 | ||
|
|
01acea3102 | ||
|
|
5ae04349da | ||
|
|
aca6fdbd0e | ||
|
|
e4bb6409ae | ||
|
|
b282ff44d4 | ||
|
|
8160c2884b | ||
|
|
c91b16d2a1 | ||
|
|
65429cebae | ||
|
|
4449b0d3c2 | ||
|
|
589f93da92 | ||
|
|
5296bd10c1 | ||
|
|
d100c014bc | ||
|
|
2cf75116d9 | ||
|
|
a45f7ac1bc | ||
|
|
e75de542df | ||
|
|
252963190b | ||
|
|
93de4c67e5 | ||
|
|
23791a45c8 | ||
|
|
355e7468e4 | ||
|
|
496ceed1d0 | ||
|
|
1205bce0ef | ||
|
|
c03fe508c1 | ||
|
|
6895e634cc | ||
|
|
86015bef78 | ||
|
|
bd724fc304 | ||
|
|
6e6f66de2e | ||
|
|
daa935b5c9 | ||
|
|
6fa1ec4f3c | ||
|
|
363ca66c2d | ||
|
|
b8f5911c4e | ||
|
|
30b74e74cd | ||
|
|
c400702272 | ||
|
|
dce846fdfd | ||
|
|
bbda08717f | ||
|
|
2eeeaf5753 | ||
|
|
7299202d01 | ||
|
|
1f63350eba | ||
|
|
cb26ad511b | ||
|
|
139621778b | ||
|
|
ae4e01adc9 | ||
|
|
6d6cafafb2 | ||
|
|
0d3c5c966b | ||
|
|
18012d9ee8 | ||
|
|
a6da5f9e77 | ||
|
|
c418074360 | ||
|
|
f0b64547c2 | ||
|
|
1f94208090 | ||
|
|
5268bf5a8c | ||
|
|
a097e29292 | ||
|
|
9f07c7940f | ||
|
|
1adcf5225b | ||
|
|
c439324451 | ||
|
|
66b46a277e | ||
|
|
9adfc04f75 | ||
|
|
28f383bae9 | ||
|
|
b04e437cfd | ||
|
|
0a00df2e7e | ||
|
|
aa76c9db2e | ||
|
|
f56471566b | ||
|
|
14544d64e4 | ||
|
|
2646b24047 | ||
|
|
ac2469077f | ||
|
|
b2b577257f | ||
|
|
8f9ffe5417 | ||
|
|
a4a0751051 | ||
|
|
904aea76ab | ||
|
|
b5c6b04b36 | ||
|
|
656b9f97f9 | ||
|
|
db66cb6e9b | ||
|
|
7e0ccce225 | ||
|
|
2ad615cd32 | ||
|
|
151668b260 | ||
|
|
f237789753 | ||
|
|
0f7cae4130 | ||
|
|
b5be62a167 | ||
|
|
6eaf44ec61 | ||
|
|
8ee0377456 | ||
|
|
d42502fab9 | ||
|
|
b534619d37 | ||
|
|
2aec0a92a5 | ||
|
|
7c3b361fa6 | ||
|
|
da8136e49d | ||
|
|
1f4a34ffc8 | ||
|
|
3b18caf229 | ||
|
|
7ca4d40d49 | ||
|
|
d844f6113d | ||
|
|
8eb3aa56ca | ||
|
|
f446a0f97f | ||
|
|
e3efa9a5e2 |
18
.github/dependabot.yml
vendored
Normal file
18
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: cargo
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: daily
|
||||||
|
open-pull-requests-limit: 3
|
||||||
|
allow:
|
||||||
|
- dependency-type: direct
|
||||||
|
- dependency-type: indirect
|
||||||
|
- package-ecosystem: cargo
|
||||||
|
directory: "/fuzz"
|
||||||
|
schedule:
|
||||||
|
interval: daily
|
||||||
|
open-pull-requests-limit: 3
|
||||||
|
allow:
|
||||||
|
- dependency-type: direct
|
||||||
|
- dependency-type: indirect
|
||||||
2
.github/workflows/quality-aarch64.yaml
vendored
2
.github/workflows/quality-aarch64.yaml
vendored
@@ -29,8 +29,6 @@ jobs:
|
|||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
override: true
|
override: true
|
||||||
components: rustfmt, clippy
|
components: rustfmt, clippy
|
||||||
- name: Install arm64 libfdt
|
|
||||||
run: wget http://ftp.us.debian.org/debian/pool/main/d/device-tree-compiler/libfdt-dev_1.6.0-1_arm64.deb && dpkg-deb -xv libfdt-dev_1.6.0-1_arm64.deb ./tlibfdtdev && mkdir -p target/debug/deps && sudo cp ./tlibfdtdev/usr/lib/aarch64-linux-gnu/libfdt.a target/debug/deps/libfdt.a && echo "libfdt installed"
|
|
||||||
- name: Formatting (rustfmt)
|
- name: Formatting (rustfmt)
|
||||||
run: cargo fmt -- --check
|
run: cargo fmt -- --check
|
||||||
- name: Clippy (kvm)
|
- name: Clippy (kvm)
|
||||||
|
|||||||
449
Cargo.lock
generated
449
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
13
Cargo.toml
13
Cargo.toml
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cloud-hypervisor"
|
name = "cloud-hypervisor"
|
||||||
version = "15.0.0"
|
version = "16.0.0"
|
||||||
authors = ["The Cloud Hypervisor Authors"]
|
authors = ["The Cloud Hypervisor Authors"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
default-run = "cloud-hypervisor"
|
default-run = "cloud-hypervisor"
|
||||||
@@ -19,13 +19,13 @@ clap = { version = "2.33.3", features = ["wrap_help"] }
|
|||||||
epoll = "4.3.1"
|
epoll = "4.3.1"
|
||||||
event_monitor = { path = "event_monitor" }
|
event_monitor = { path = "event_monitor" }
|
||||||
hypervisor = { path = "hypervisor" }
|
hypervisor = { path = "hypervisor" }
|
||||||
libc = "0.2.94"
|
libc = "0.2.96"
|
||||||
log = { version = "0.4.14", features = ["std"] }
|
log = { version = "0.4.14", features = ["std"] }
|
||||||
option_parser = { path = "option_parser" }
|
option_parser = { path = "option_parser" }
|
||||||
seccomp = { git = "https://github.com/firecracker-microvm/firecracker", tag = "v0.24.2" }
|
seccomp = { git = "https://github.com/firecracker-microvm/firecracker", tag = "v0.24.4" }
|
||||||
serde_json = "1.0.64"
|
serde_json = "1.0.64"
|
||||||
signal-hook = "0.3.8"
|
signal-hook = "0.3.9"
|
||||||
thiserror = "1.0.24"
|
thiserror = "1.0.25"
|
||||||
vmm = { path = "vmm" }
|
vmm = { path = "vmm" }
|
||||||
vmm-sys-util = "0.8.0"
|
vmm-sys-util = "0.8.0"
|
||||||
vm-memory = "0.5.0"
|
vm-memory = "0.5.0"
|
||||||
@@ -36,6 +36,8 @@ clap = { version = "2.33.3", features = ["wrap_help"] }
|
|||||||
# List of patched crates
|
# List of patched crates
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.4.0", features = ["with-serde", "fam-wrappers"] }
|
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.4.0", features = ["with-serde", "fam-wrappers"] }
|
||||||
|
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch" }
|
||||||
|
vm-memory = { git = "https://github.com/rust-vmm/vm-memory", rev = "5bd7138758183a73ac0da27ce40c004d95f1a7e9"}
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
credibility = "0.1.3"
|
credibility = "0.1.3"
|
||||||
@@ -66,7 +68,6 @@ members = [
|
|||||||
"acpi_tables",
|
"acpi_tables",
|
||||||
"api_client",
|
"api_client",
|
||||||
"arch",
|
"arch",
|
||||||
"arch_gen",
|
|
||||||
"block_util",
|
"block_util",
|
||||||
"devices",
|
"devices",
|
||||||
"event_monitor",
|
"event_monitor",
|
||||||
|
|||||||
15
Jenkinsfile
vendored
15
Jenkinsfile
vendored
@@ -46,6 +46,7 @@ pipeline{
|
|||||||
timeout(time: 1, unit: 'HOURS')
|
timeout(time: 1, unit: 'HOURS')
|
||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
|
sh "sudo modprobe openvswitch"
|
||||||
sh "scripts/dev_cli.sh tests --integration"
|
sh "scripts/dev_cli.sh tests --integration"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,6 +70,7 @@ pipeline{
|
|||||||
timeout(time: 1, unit: 'HOURS')
|
timeout(time: 1, unit: 'HOURS')
|
||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
|
sh "sudo modprobe openvswitch"
|
||||||
sh "scripts/dev_cli.sh tests --integration"
|
sh "scripts/dev_cli.sh tests --integration"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,6 +100,7 @@ pipeline{
|
|||||||
timeout(time: 1, unit: 'HOURS')
|
timeout(time: 1, unit: 'HOURS')
|
||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
|
sh "sudo modprobe openvswitch"
|
||||||
sh "scripts/dev_cli.sh tests --integration --libc musl"
|
sh "scripts/dev_cli.sh tests --integration --libc musl"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,7 +108,10 @@ pipeline{
|
|||||||
}
|
}
|
||||||
stage ('Worker build SGX') {
|
stage ('Worker build SGX') {
|
||||||
agent { node { label 'bionic-sgx' } }
|
agent { node { label 'bionic-sgx' } }
|
||||||
when { branch 'master' }
|
when {
|
||||||
|
beforeAgent true
|
||||||
|
branch 'master'
|
||||||
|
}
|
||||||
stages {
|
stages {
|
||||||
stage ('Checkout') {
|
stage ('Checkout') {
|
||||||
steps {
|
steps {
|
||||||
@@ -138,7 +144,10 @@ pipeline{
|
|||||||
}
|
}
|
||||||
stage ('Worker build VFIO') {
|
stage ('Worker build VFIO') {
|
||||||
agent { node { label 'bionic-vfio' } }
|
agent { node { label 'bionic-vfio' } }
|
||||||
when { branch 'master' }
|
when {
|
||||||
|
beforeAgent true
|
||||||
|
branch 'master'
|
||||||
|
}
|
||||||
stages {
|
stages {
|
||||||
stage ('Checkout') {
|
stage ('Checkout') {
|
||||||
steps {
|
steps {
|
||||||
@@ -170,7 +179,7 @@ pipeline{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage ('Worker build - Windows guest') {
|
stage ('Worker build - Windows guest') {
|
||||||
agent { node { label 'groovy-win' } }
|
agent { node { label 'groovy' } }
|
||||||
stages {
|
stages {
|
||||||
stage ('Checkout') {
|
stage ('Checkout') {
|
||||||
steps {
|
steps {
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ $ popd
|
|||||||
#### Booting the guest VM
|
#### Booting the guest VM
|
||||||
|
|
||||||
Now we can directly boot into our custom kernel and make it use the Ubuntu root partition.
|
Now we can directly boot into our custom kernel and make it use the Ubuntu root partition.
|
||||||
If we want to have 4 vCPUs and 512 MBytes of memory:
|
If we want to have 4 vCPUs and 1024 MBytes of memory:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ pushd $CLOUDH
|
$ pushd $CLOUDH
|
||||||
|
|||||||
@@ -6,4 +6,3 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
vm-memory = "0.5.0"
|
vm-memory = "0.5.0"
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,15 @@ impl GenericAddress {
|
|||||||
address: u64::from(address),
|
address: u64::from(address),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn mmio_address<T>(address: u64) -> Self {
|
||||||
|
GenericAddress {
|
||||||
|
address_space_id: 0,
|
||||||
|
register_bit_width: 8 * std::mem::size_of::<T>() as u8,
|
||||||
|
register_bit_offset: 0,
|
||||||
|
access_size: std::mem::size_of::<T>() as u8,
|
||||||
|
address,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Sdt {
|
pub struct Sdt {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
name = "arch"
|
name = "arch"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["The Chromium OS Authors"]
|
authors = ["The Chromium OS Authors"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
@@ -11,16 +12,16 @@ tdx = []
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
acpi_tables = { path = "../acpi_tables", optional = true }
|
acpi_tables = { path = "../acpi_tables", optional = true }
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
arch_gen = { path = "../arch_gen" }
|
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
hypervisor = { path = "../hypervisor" }
|
hypervisor = { path = "../hypervisor" }
|
||||||
libc = "0.2.94"
|
libc = "0.2.96"
|
||||||
linux-loader = { version = "0.3.0", features = ["elf", "bzimage", "pe"] }
|
linux-loader = { version = "0.3.0", features = ["elf", "bzimage", "pe"] }
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
serde = {version = ">=1.0.27", features = ["rc"] }
|
serde = {version = ">=1.0.27", features = ["rc"] }
|
||||||
serde_derive = ">=1.0.27"
|
|
||||||
serde_json = ">=1.0.9"
|
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
vm-memory = { version = "0.5.0", features = ["backend-mmap"] }
|
versionize = "0.1.6"
|
||||||
|
versionize_derive = "0.1.4"
|
||||||
|
vm-fdt = { git = "https://github.com/rust-vmm/vm-fdt", branch = "master" }
|
||||||
|
vm-memory = { version = "0.5.0", features = ["backend-mmap", "backend-bitmap"] }
|
||||||
vm-migration = { path = "../vm-migration" }
|
vm-migration = { path = "../vm-migration" }
|
||||||
|
|
||||||
|
|||||||
@@ -6,23 +6,22 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the THIRD-PARTY file.
|
// found in the THIRD-PARTY file.
|
||||||
|
|
||||||
use libc::{c_char, c_int, c_void};
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ffi::{CStr, CString, NulError};
|
use std::ffi::CStr;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::ptr::null;
|
use std::result;
|
||||||
use std::{io, result};
|
|
||||||
|
|
||||||
use super::super::DeviceType;
|
use super::super::DeviceType;
|
||||||
|
use super::super::GuestMemoryMmap;
|
||||||
use super::super::InitramfsConfig;
|
use super::super::InitramfsConfig;
|
||||||
use super::get_fdt_addr;
|
use super::get_fdt_addr;
|
||||||
use super::gic::GicDevice;
|
use super::gic::GicDevice;
|
||||||
use super::layout::{
|
use super::layout::{
|
||||||
FDT_MAX_SIZE, MEM_32BIT_DEVICES_SIZE, MEM_32BIT_DEVICES_START, PCI_MMCONFIG_SIZE,
|
IRQ_BASE, MEM_32BIT_DEVICES_SIZE, MEM_32BIT_DEVICES_START, MEM_PCI_IO_SIZE, MEM_PCI_IO_START,
|
||||||
PCI_MMCONFIG_START,
|
PCI_HIGH_BASE, PCI_MMCONFIG_SIZE, PCI_MMCONFIG_START,
|
||||||
};
|
};
|
||||||
use crate::aarch64::fdt::Error::CstringFdtTransform;
|
use vm_fdt::{FdtWriter, FdtWriterResult};
|
||||||
use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryError, GuestMemoryMmap};
|
use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryError};
|
||||||
|
|
||||||
// This is a value for uniquely identifying the FDT node declaring the interrupt controller.
|
// This is a value for uniquely identifying the FDT node declaring the interrupt controller.
|
||||||
const GIC_PHANDLE: u32 = 1;
|
const GIC_PHANDLE: u32 = 1;
|
||||||
@@ -51,22 +50,6 @@ const IRQ_TYPE_LEVEL_HI: u32 = 4;
|
|||||||
// System Power Down
|
// System Power Down
|
||||||
const KEY_POWER: u32 = 116;
|
const KEY_POWER: u32 = 116;
|
||||||
|
|
||||||
// This links to libfdt which handles the creation of the binary blob
|
|
||||||
// flattened device tree (fdt) that is passed to the kernel and indicates
|
|
||||||
// the hardware configuration of the machine.
|
|
||||||
#[link(name = "fdt")]
|
|
||||||
extern "C" {
|
|
||||||
fn fdt_create(buf: *mut c_void, bufsize: c_int) -> c_int;
|
|
||||||
fn fdt_finish_reservemap(fdt: *mut c_void) -> c_int;
|
|
||||||
fn fdt_begin_node(fdt: *mut c_void, name: *const c_char) -> c_int;
|
|
||||||
fn fdt_property(fdt: *mut c_void, name: *const c_char, val: *const c_void, len: c_int)
|
|
||||||
-> c_int;
|
|
||||||
fn fdt_end_node(fdt: *mut c_void) -> c_int;
|
|
||||||
fn fdt_open_into(fdt: *const c_void, buf: *mut c_void, bufsize: c_int) -> c_int;
|
|
||||||
fn fdt_finish(fdt: *const c_void) -> c_int;
|
|
||||||
fn fdt_pack(fdt: *mut c_void) -> c_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait for devices to be added to the Flattened Device Tree.
|
/// Trait for devices to be added to the Flattened Device Tree.
|
||||||
pub trait DeviceInfoForFdt {
|
pub trait DeviceInfoForFdt {
|
||||||
/// Returns the address where this device will be loaded.
|
/// Returns the address where this device will be loaded.
|
||||||
@@ -80,16 +63,6 @@ pub trait DeviceInfoForFdt {
|
|||||||
/// Errors thrown while configuring the Flattened Device Tree for aarch64.
|
/// Errors thrown while configuring the Flattened Device Tree for aarch64.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Failed to append node to the FDT.
|
|
||||||
AppendFdtNode(io::Error),
|
|
||||||
/// Failed to append a property to the FDT.
|
|
||||||
AppendFdtProperty(io::Error),
|
|
||||||
/// Syscall for creating FDT failed.
|
|
||||||
CreateFdt(io::Error),
|
|
||||||
/// Failed to obtain a C style string.
|
|
||||||
CstringFdtTransform(NulError),
|
|
||||||
/// Failure in calling syscall for terminating this FDT.
|
|
||||||
FinishFdtReserveMap(io::Error),
|
|
||||||
/// Failure in writing FDT in memory.
|
/// Failure in writing FDT in memory.
|
||||||
WriteFdtToMemory(GuestMemoryError),
|
WriteFdtToMemory(GuestMemoryError),
|
||||||
}
|
}
|
||||||
@@ -104,29 +77,27 @@ pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHash
|
|||||||
gic_device: &dyn GicDevice,
|
gic_device: &dyn GicDevice,
|
||||||
initrd: &Option<InitramfsConfig>,
|
initrd: &Option<InitramfsConfig>,
|
||||||
pci_space_address: &(u64, u64),
|
pci_space_address: &(u64, u64),
|
||||||
) -> Result<Vec<u8>> {
|
) -> FdtWriterResult<Vec<u8>> {
|
||||||
// Allocate stuff necessary for the holding the blob.
|
// Allocate stuff necessary for the holding the blob.
|
||||||
let mut fdt = vec![0; FDT_MAX_SIZE];
|
let mut fdt = FdtWriter::new(&[]).unwrap();
|
||||||
|
|
||||||
allocate_fdt(&mut fdt)?;
|
|
||||||
|
|
||||||
// For an explanation why these nodes were introduced in the blob take a look at
|
// For an explanation why these nodes were introduced in the blob take a look at
|
||||||
// https://github.com/torvalds/linux/blob/master/Documentation/devicetree/booting-without-of.txt#L845
|
// https://github.com/torvalds/linux/blob/master/Documentation/devicetree/booting-without-of.txt#L845
|
||||||
// Look for "Required nodes and properties".
|
// Look for "Required nodes and properties".
|
||||||
|
|
||||||
// Header or the root node as per above mentioned documentation.
|
// Header or the root node as per above mentioned documentation.
|
||||||
append_begin_node(&mut fdt, "")?;
|
let root_node = fdt.begin_node("")?;
|
||||||
append_property_string(&mut fdt, "compatible", "linux,dummy-virt")?;
|
fdt.property_string("compatible", "linux,dummy-virt")?;
|
||||||
// For info on #address-cells and size-cells read "Note about cells and address representation"
|
// For info on #address-cells and size-cells read "Note about cells and address representation"
|
||||||
// from the above mentioned txt file.
|
// from the above mentioned txt file.
|
||||||
append_property_u32(&mut fdt, "#address-cells", ADDRESS_CELLS)?;
|
fdt.property_u32("#address-cells", ADDRESS_CELLS)?;
|
||||||
append_property_u32(&mut fdt, "#size-cells", SIZE_CELLS)?;
|
fdt.property_u32("#size-cells", SIZE_CELLS)?;
|
||||||
// This is not mandatory but we use it to point the root node to the node
|
// This is not mandatory but we use it to point the root node to the node
|
||||||
// containing description of the interrupt controller for this VM.
|
// containing description of the interrupt controller for this VM.
|
||||||
append_property_u32(&mut fdt, "interrupt-parent", GIC_PHANDLE)?;
|
fdt.property_u32("interrupt-parent", GIC_PHANDLE)?;
|
||||||
create_cpu_nodes(&mut fdt, &vcpu_mpidr)?;
|
create_cpu_nodes(&mut fdt, &vcpu_mpidr)?;
|
||||||
create_memory_node(&mut fdt, guest_mem)?;
|
create_memory_node(&mut fdt, guest_mem)?;
|
||||||
create_chosen_node(&mut fdt, cmdline, initrd)?;
|
create_chosen_node(&mut fdt, cmdline.to_str().unwrap(), initrd)?;
|
||||||
create_gic_node(&mut fdt, gic_device)?;
|
create_gic_node(&mut fdt, gic_device)?;
|
||||||
create_timer_node(&mut fdt)?;
|
create_timer_node(&mut fdt)?;
|
||||||
create_clock_node(&mut fdt)?;
|
create_clock_node(&mut fdt)?;
|
||||||
@@ -135,307 +106,136 @@ pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHash
|
|||||||
create_pci_nodes(&mut fdt, pci_space_address.0, pci_space_address.1)?;
|
create_pci_nodes(&mut fdt, pci_space_address.0, pci_space_address.1)?;
|
||||||
|
|
||||||
// End Header node.
|
// End Header node.
|
||||||
append_end_node(&mut fdt)?;
|
fdt.end_node(root_node)?;
|
||||||
|
|
||||||
// Allocate another buffer so we can format and then write fdt to guest.
|
let fdt_final = fdt.finish()?;
|
||||||
let mut fdt_final = vec![0; FDT_MAX_SIZE];
|
|
||||||
finish_fdt(&mut fdt, &mut fdt_final)?;
|
|
||||||
|
|
||||||
// Write FDT to memory.
|
|
||||||
let fdt_address = GuestAddress(get_fdt_addr(&guest_mem));
|
|
||||||
guest_mem
|
|
||||||
.write_slice(fdt_final.as_slice(), fdt_address)
|
|
||||||
.map_err(Error::WriteFdtToMemory)?;
|
|
||||||
Ok(fdt_final)
|
Ok(fdt_final)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Following are auxiliary functions for allocating and finishing the FDT.
|
pub fn write_fdt_to_memory(fdt_final: Vec<u8>, guest_mem: &GuestMemoryMmap) -> Result<()> {
|
||||||
fn allocate_fdt(fdt: &mut Vec<u8>) -> Result<()> {
|
// Write FDT to memory.
|
||||||
// Safe since we allocated this array with FDT_MAX_SIZE.
|
let fdt_address = GuestAddress(get_fdt_addr());
|
||||||
let mut fdt_ret = unsafe { fdt_create(fdt.as_mut_ptr() as *mut c_void, FDT_MAX_SIZE as c_int) };
|
guest_mem
|
||||||
|
.write_slice(fdt_final.as_slice(), fdt_address)
|
||||||
if fdt_ret != 0 {
|
.map_err(Error::WriteFdtToMemory)?;
|
||||||
return Err(Error::CreateFdt(io::Error::last_os_error()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// The flattened device trees created with fdt_create() contains a list of
|
|
||||||
// reserved memory areas. We need to call `fdt_finish_reservemap` so as to make sure that there is a
|
|
||||||
// terminator in the reservemap list and whatever happened to be at the
|
|
||||||
// start of the FDT data section would end up being interpreted as
|
|
||||||
// reservemap entries.
|
|
||||||
// Safe since we previously allocated this array.
|
|
||||||
fdt_ret = unsafe { fdt_finish_reservemap(fdt.as_mut_ptr() as *mut c_void) };
|
|
||||||
if fdt_ret != 0 {
|
|
||||||
return Err(Error::FinishFdtReserveMap(io::Error::last_os_error()));
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish_fdt(from_fdt: &mut Vec<u8>, to_fdt: &mut Vec<u8>) -> Result<()> {
|
|
||||||
// Safe since we allocated `fdt_final` and previously passed in its size.
|
|
||||||
let mut fdt_ret = unsafe { fdt_finish(from_fdt.as_mut_ptr() as *mut c_void) };
|
|
||||||
if fdt_ret != 0 {
|
|
||||||
return Err(Error::FinishFdtReserveMap(io::Error::last_os_error()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Safe because we allocated both arrays with the correct size.
|
|
||||||
fdt_ret = unsafe {
|
|
||||||
fdt_open_into(
|
|
||||||
from_fdt.as_mut_ptr() as *mut c_void,
|
|
||||||
to_fdt.as_mut_ptr() as *mut c_void,
|
|
||||||
FDT_MAX_SIZE as i32,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if fdt_ret != 0 {
|
|
||||||
return Err(Error::FinishFdtReserveMap(io::Error::last_os_error()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Safe since we allocated `to_fdt`.
|
|
||||||
fdt_ret = unsafe { fdt_pack(to_fdt.as_mut_ptr() as *mut c_void) };
|
|
||||||
if fdt_ret != 0 {
|
|
||||||
return Err(Error::FinishFdtReserveMap(io::Error::last_os_error()));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Following are auxiliary functions for appending nodes to FDT.
|
|
||||||
fn append_begin_node(fdt: &mut Vec<u8>, name: &str) -> Result<()> {
|
|
||||||
let cstr_name = CString::new(name).map_err(CstringFdtTransform)?;
|
|
||||||
|
|
||||||
// Safe because we allocated fdt and converted name to a CString
|
|
||||||
let fdt_ret = unsafe { fdt_begin_node(fdt.as_mut_ptr() as *mut c_void, cstr_name.as_ptr()) };
|
|
||||||
if fdt_ret != 0 {
|
|
||||||
return Err(Error::AppendFdtNode(io::Error::last_os_error()));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn append_end_node(fdt: &mut Vec<u8>) -> Result<()> {
|
|
||||||
// Safe because we allocated fdt.
|
|
||||||
let fdt_ret = unsafe { fdt_end_node(fdt.as_mut_ptr() as *mut c_void) };
|
|
||||||
if fdt_ret != 0 {
|
|
||||||
return Err(Error::AppendFdtNode(io::Error::last_os_error()));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Following are auxiliary functions for appending property nodes to the nodes of the FDT.
|
|
||||||
fn append_property_u32(fdt: &mut Vec<u8>, name: &str, val: u32) -> Result<()> {
|
|
||||||
append_property(fdt, name, &to_be32(val))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn append_property_u64(fdt: &mut Vec<u8>, name: &str, val: u64) -> Result<()> {
|
|
||||||
append_property(fdt, name, &to_be64(val))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn append_property_string(fdt: &mut Vec<u8>, name: &str, value: &str) -> Result<()> {
|
|
||||||
let cstr_value = CString::new(value).map_err(CstringFdtTransform)?;
|
|
||||||
append_property_cstring(fdt, name, &cstr_value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn append_property_cstring(fdt: &mut Vec<u8>, name: &str, cstr_value: &CStr) -> Result<()> {
|
|
||||||
let value_bytes = cstr_value.to_bytes_with_nul();
|
|
||||||
let cstr_name = CString::new(name).map_err(CstringFdtTransform)?;
|
|
||||||
// Safe because we allocated fdt, converted name and value to CStrings
|
|
||||||
let fdt_ret = unsafe {
|
|
||||||
fdt_property(
|
|
||||||
fdt.as_mut_ptr() as *mut c_void,
|
|
||||||
cstr_name.as_ptr(),
|
|
||||||
value_bytes.as_ptr() as *mut c_void,
|
|
||||||
value_bytes.len() as i32,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if fdt_ret != 0 {
|
|
||||||
return Err(Error::AppendFdtProperty(io::Error::last_os_error()));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn append_property_null(fdt: &mut Vec<u8>, name: &str) -> Result<()> {
|
|
||||||
let cstr_name = CString::new(name).map_err(CstringFdtTransform)?;
|
|
||||||
|
|
||||||
// Safe because we allocated fdt, converted name to a CString
|
|
||||||
let fdt_ret = unsafe {
|
|
||||||
fdt_property(
|
|
||||||
fdt.as_mut_ptr() as *mut c_void,
|
|
||||||
cstr_name.as_ptr(),
|
|
||||||
null(),
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if fdt_ret != 0 {
|
|
||||||
return Err(Error::AppendFdtProperty(io::Error::last_os_error()));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn append_property(fdt: &mut Vec<u8>, name: &str, val: &[u8]) -> Result<()> {
|
|
||||||
let cstr_name = CString::new(name).map_err(CstringFdtTransform)?;
|
|
||||||
let val_ptr = val.as_ptr() as *const c_void;
|
|
||||||
|
|
||||||
// Safe because we allocated fdt and converted name to a CString
|
|
||||||
let fdt_ret = unsafe {
|
|
||||||
fdt_property(
|
|
||||||
fdt.as_mut_ptr() as *mut c_void,
|
|
||||||
cstr_name.as_ptr(),
|
|
||||||
val_ptr,
|
|
||||||
val.len() as i32,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if fdt_ret != 0 {
|
|
||||||
return Err(Error::AppendFdtProperty(io::Error::last_os_error()));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Auxiliary functions for writing u32/u64 numbers in big endian order.
|
|
||||||
fn to_be32(input: u32) -> [u8; 4] {
|
|
||||||
u32::to_be_bytes(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_be64(input: u64) -> [u8; 8] {
|
|
||||||
u64::to_be_bytes(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper functions for generating a properly formatted byte vector using 32-bit/64-bit cells.
|
|
||||||
fn generate_prop32(cells: &[u32]) -> Vec<u8> {
|
|
||||||
let mut ret: Vec<u8> = Vec::new();
|
|
||||||
for &e in cells {
|
|
||||||
ret.extend(to_be32(e).iter());
|
|
||||||
}
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_prop64(cells: &[u64]) -> Vec<u8> {
|
|
||||||
let mut ret: Vec<u8> = Vec::new();
|
|
||||||
for &e in cells {
|
|
||||||
ret.extend(to_be64(e).iter());
|
|
||||||
}
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// Following are the auxiliary function for creating the different nodes that we append to our FDT.
|
// Following are the auxiliary function for creating the different nodes that we append to our FDT.
|
||||||
fn create_cpu_nodes(fdt: &mut Vec<u8>, vcpu_mpidr: &[u64]) -> Result<()> {
|
fn create_cpu_nodes(fdt: &mut FdtWriter, vcpu_mpidr: &[u64]) -> FdtWriterResult<()> {
|
||||||
// See https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/arm/cpus.yaml.
|
// See https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/arm/cpus.yaml.
|
||||||
append_begin_node(fdt, "cpus")?;
|
let cpus_node = fdt.begin_node("cpus")?;
|
||||||
// As per documentation, on ARM v8 64-bit systems value should be set to 2.
|
fdt.property_u32("#address-cells", 0x1)?;
|
||||||
append_property_u32(fdt, "#address-cells", 0x02)?;
|
fdt.property_u32("#size-cells", 0x0)?;
|
||||||
append_property_u32(fdt, "#size-cells", 0x0)?;
|
|
||||||
let num_cpus = vcpu_mpidr.len();
|
let num_cpus = vcpu_mpidr.len();
|
||||||
|
|
||||||
for (cpu_index, mpidr) in vcpu_mpidr.iter().enumerate().take(num_cpus) {
|
for cpu_id in 0..num_cpus {
|
||||||
let cpu_name = format!("cpu@{:x}", cpu_index);
|
let cpu_name = format!("cpu@{:x}", cpu_id);
|
||||||
append_begin_node(fdt, &cpu_name)?;
|
let cpu_node = fdt.begin_node(&cpu_name)?;
|
||||||
append_property_string(fdt, "device_type", "cpu")?;
|
fdt.property_string("device_type", "cpu")?;
|
||||||
append_property_string(fdt, "compatible", "arm,arm-v8")?;
|
fdt.property_string("compatible", "arm,arm-v8")?;
|
||||||
if num_cpus > 1 {
|
if num_cpus > 1 {
|
||||||
// This is required on armv8 64-bit. See aforementioned documentation.
|
// This is required on armv8 64-bit. See aforementioned documentation.
|
||||||
append_property_string(fdt, "enable-method", "psci")?;
|
fdt.property_string("enable-method", "psci")?;
|
||||||
}
|
}
|
||||||
// Set the field to first 24 bits of the MPIDR - Multiprocessor Affinity Register.
|
fdt.property_u32("reg", cpu_id as u32)?;
|
||||||
// See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0488c/BABHBJCI.html.
|
fdt.end_node(cpu_node)?;
|
||||||
append_property_u64(fdt, "reg", mpidr & 0x7FFFFF)?;
|
|
||||||
append_end_node(fdt)?;
|
|
||||||
}
|
}
|
||||||
append_end_node(fdt)?;
|
fdt.end_node(cpus_node)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_memory_node(fdt: &mut Vec<u8>, guest_mem: &GuestMemoryMmap) -> Result<()> {
|
fn create_memory_node(fdt: &mut FdtWriter, guest_mem: &GuestMemoryMmap) -> FdtWriterResult<()> {
|
||||||
let mem_size = guest_mem.last_addr().raw_value() - super::layout::RAM_64BIT_START + 1;
|
let mem_size = guest_mem.last_addr().raw_value() - super::layout::RAM_64BIT_START + 1;
|
||||||
// See https://github.com/torvalds/linux/blob/master/Documentation/devicetree/booting-without-of.txt#L960
|
// See https://github.com/torvalds/linux/blob/master/Documentation/devicetree/booting-without-of.txt#L960
|
||||||
// for an explanation of this.
|
// for an explanation of this.
|
||||||
let mem_reg_prop = generate_prop64(&[super::layout::RAM_64BIT_START as u64, mem_size as u64]);
|
let mem_reg_prop = [super::layout::RAM_64BIT_START as u64, mem_size as u64];
|
||||||
|
|
||||||
|
let memory_node = fdt.begin_node("memory")?;
|
||||||
|
fdt.property_string("device_type", "memory")?;
|
||||||
|
fdt.property_array_u64("reg", &mem_reg_prop)?;
|
||||||
|
fdt.end_node(memory_node)?;
|
||||||
|
|
||||||
append_begin_node(fdt, "memory")?;
|
|
||||||
append_property_string(fdt, "device_type", "memory")?;
|
|
||||||
append_property(fdt, "reg", &mem_reg_prop)?;
|
|
||||||
append_end_node(fdt)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_chosen_node(
|
fn create_chosen_node(
|
||||||
fdt: &mut Vec<u8>,
|
fdt: &mut FdtWriter,
|
||||||
cmdline: &CStr,
|
cmdline: &str,
|
||||||
initrd: &Option<InitramfsConfig>,
|
initrd: &Option<InitramfsConfig>,
|
||||||
) -> Result<()> {
|
) -> FdtWriterResult<()> {
|
||||||
append_begin_node(fdt, "chosen")?;
|
let chosen_node = fdt.begin_node("chosen")?;
|
||||||
append_property_cstring(fdt, "bootargs", cmdline)?;
|
fdt.property_string("bootargs", cmdline)?;
|
||||||
|
|
||||||
if let Some(initrd_config) = initrd {
|
if let Some(initrd_config) = initrd {
|
||||||
append_property_u64(
|
let initrd_start = initrd_config.address.raw_value() as u64;
|
||||||
fdt,
|
let initrd_end = initrd_config.address.raw_value() + initrd_config.size as u64;
|
||||||
"linux,initrd-start",
|
fdt.property_u64("linux,initrd-start", initrd_start)?;
|
||||||
initrd_config.address.raw_value() as u64,
|
fdt.property_u64("linux,initrd-end", initrd_end)?;
|
||||||
)?;
|
|
||||||
append_property_u64(
|
|
||||||
fdt,
|
|
||||||
"linux,initrd-end",
|
|
||||||
initrd_config.address.raw_value() + initrd_config.size as u64,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
append_end_node(fdt)?;
|
fdt.end_node(chosen_node)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_gic_node(fdt: &mut Vec<u8>, gic_device: &dyn GicDevice) -> Result<()> {
|
fn create_gic_node(fdt: &mut FdtWriter, gic_device: &dyn GicDevice) -> FdtWriterResult<()> {
|
||||||
let gic_reg_prop = generate_prop64(gic_device.device_properties());
|
let gic_reg_prop = gic_device.device_properties();
|
||||||
|
|
||||||
append_begin_node(fdt, "intc")?;
|
let intc_node = fdt.begin_node("intc")?;
|
||||||
append_property_string(fdt, "compatible", gic_device.fdt_compatibility())?;
|
|
||||||
append_property_null(fdt, "interrupt-controller")?;
|
fdt.property_string("compatible", gic_device.fdt_compatibility())?;
|
||||||
|
fdt.property_null("interrupt-controller")?;
|
||||||
// "interrupt-cells" field specifies the number of cells needed to encode an
|
// "interrupt-cells" field specifies the number of cells needed to encode an
|
||||||
// interrupt source. The type shall be a <u32> and the value shall be 3 if no PPI affinity description
|
// interrupt source. The type shall be a <u32> and the value shall be 3 if no PPI affinity description
|
||||||
// is required.
|
// is required.
|
||||||
append_property_u32(fdt, "#interrupt-cells", 3)?;
|
fdt.property_u32("#interrupt-cells", 3)?;
|
||||||
append_property(fdt, "reg", &gic_reg_prop)?;
|
fdt.property_array_u64("reg", &gic_reg_prop)?;
|
||||||
append_property_u32(fdt, "phandle", GIC_PHANDLE)?;
|
fdt.property_u32("phandle", GIC_PHANDLE)?;
|
||||||
append_property_u32(fdt, "#address-cells", 2)?;
|
fdt.property_u32("#address-cells", 2)?;
|
||||||
append_property_u32(fdt, "#size-cells", 2)?;
|
fdt.property_u32("#size-cells", 2)?;
|
||||||
append_property_null(fdt, "ranges")?;
|
fdt.property_null("ranges")?;
|
||||||
let gic_intr = [
|
|
||||||
|
let gic_intr_prop = [
|
||||||
GIC_FDT_IRQ_TYPE_PPI,
|
GIC_FDT_IRQ_TYPE_PPI,
|
||||||
gic_device.fdt_maint_irq(),
|
gic_device.fdt_maint_irq(),
|
||||||
IRQ_TYPE_LEVEL_HI,
|
IRQ_TYPE_LEVEL_HI,
|
||||||
];
|
];
|
||||||
let gic_intr_prop = generate_prop32(&gic_intr);
|
fdt.property_array_u32("interrupts", &gic_intr_prop)?;
|
||||||
|
|
||||||
append_property(fdt, "interrupts", &gic_intr_prop)?;
|
|
||||||
|
|
||||||
if gic_device.msi_compatible() {
|
if gic_device.msi_compatible() {
|
||||||
append_begin_node(fdt, "msic")?;
|
let msic_node = fdt.begin_node("msic")?;
|
||||||
append_property_string(fdt, "compatible", gic_device.msi_compatibility())?;
|
fdt.property_string("compatible", gic_device.msi_compatibility())?;
|
||||||
append_property_null(fdt, "msi-controller")?;
|
fdt.property_null("msi-controller")?;
|
||||||
append_property_u32(fdt, "phandle", MSI_PHANDLE)?;
|
fdt.property_u32("phandle", MSI_PHANDLE)?;
|
||||||
let msi_reg_prop = generate_prop64(gic_device.msi_properties());
|
let msi_reg_prop = gic_device.msi_properties();
|
||||||
append_property(fdt, "reg", &msi_reg_prop)?;
|
fdt.property_array_u64("reg", &msi_reg_prop)?;
|
||||||
append_end_node(fdt)?;
|
fdt.end_node(msic_node)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
append_end_node(fdt)?;
|
fdt.end_node(intc_node)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_clock_node(fdt: &mut Vec<u8>) -> Result<()> {
|
fn create_clock_node(fdt: &mut FdtWriter) -> FdtWriterResult<()> {
|
||||||
// The Advanced Peripheral Bus (APB) is part of the Advanced Microcontroller Bus Architecture
|
// The Advanced Peripheral Bus (APB) is part of the Advanced Microcontroller Bus Architecture
|
||||||
// (AMBA) protocol family. It defines a low-cost interface that is optimized for minimal power
|
// (AMBA) protocol family. It defines a low-cost interface that is optimized for minimal power
|
||||||
// consumption and reduced interface complexity.
|
// consumption and reduced interface complexity.
|
||||||
// PCLK is the clock source and this node defines exactly the clock for the APB.
|
// PCLK is the clock source and this node defines exactly the clock for the APB.
|
||||||
append_begin_node(fdt, "apb-pclk")?;
|
let clock_node = fdt.begin_node("apb-pclk")?;
|
||||||
append_property_string(fdt, "compatible", "fixed-clock")?;
|
fdt.property_string("compatible", "fixed-clock")?;
|
||||||
append_property_u32(fdt, "#clock-cells", 0x0)?;
|
fdt.property_u32("#clock-cells", 0x0)?;
|
||||||
append_property_u32(fdt, "clock-frequency", 24000000)?;
|
fdt.property_u32("clock-frequency", 24000000)?;
|
||||||
append_property_string(fdt, "clock-output-names", "clk24mhz")?;
|
fdt.property_string("clock-output-names", "clk24mhz")?;
|
||||||
append_property_u32(fdt, "phandle", CLOCK_PHANDLE)?;
|
fdt.property_u32("phandle", CLOCK_PHANDLE)?;
|
||||||
append_end_node(fdt)?;
|
fdt.end_node(clock_node)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_timer_node(fdt: &mut Vec<u8>) -> Result<()> {
|
fn create_timer_node(fdt: &mut FdtWriter) -> FdtWriterResult<()> {
|
||||||
// See
|
// See
|
||||||
// https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/interrupt-controller/arch_timer.txt
|
// https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/interrupt-controller/arch_timer.txt
|
||||||
// These are fixed interrupt numbers for the timer device.
|
// These are fixed interrupt numbers for the timer device.
|
||||||
@@ -448,123 +248,136 @@ fn create_timer_node(fdt: &mut Vec<u8>) -> Result<()> {
|
|||||||
timer_reg_cells.push(irq);
|
timer_reg_cells.push(irq);
|
||||||
timer_reg_cells.push(IRQ_TYPE_LEVEL_HI);
|
timer_reg_cells.push(IRQ_TYPE_LEVEL_HI);
|
||||||
}
|
}
|
||||||
let timer_reg_prop = generate_prop32(timer_reg_cells.as_slice());
|
|
||||||
|
|
||||||
append_begin_node(fdt, "timer")?;
|
let timer_node = fdt.begin_node("timer")?;
|
||||||
append_property_string(fdt, "compatible", compatible)?;
|
fdt.property_string("compatible", compatible)?;
|
||||||
append_property_null(fdt, "always-on")?;
|
fdt.property_null("always-on")?;
|
||||||
append_property(fdt, "interrupts", &timer_reg_prop)?;
|
fdt.property_array_u32("interrupts", &timer_reg_cells)?;
|
||||||
append_end_node(fdt)?;
|
fdt.end_node(timer_node)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_psci_node(fdt: &mut Vec<u8>) -> Result<()> {
|
fn create_psci_node(fdt: &mut FdtWriter) -> FdtWriterResult<()> {
|
||||||
let compatible = "arm,psci-0.2";
|
let compatible = "arm,psci-0.2";
|
||||||
append_begin_node(fdt, "psci")?;
|
let psci_node = fdt.begin_node("psci")?;
|
||||||
append_property_string(fdt, "compatible", compatible)?;
|
fdt.property_string("compatible", compatible)?;
|
||||||
// Two methods available: hvc and smc.
|
// Two methods available: hvc and smc.
|
||||||
// As per documentation, PSCI calls between a guest and hypervisor may use the HVC conduit instead of SMC.
|
// As per documentation, PSCI calls between a guest and hypervisor may use the HVC conduit instead of SMC.
|
||||||
// So, since we are using kvm, we need to use hvc.
|
// So, since we are using kvm, we need to use hvc.
|
||||||
append_property_string(fdt, "method", "hvc")?;
|
fdt.property_string("method", "hvc")?;
|
||||||
append_end_node(fdt)?;
|
fdt.end_node(psci_node)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_virtio_node<T: DeviceInfoForFdt + Clone + Debug>(
|
fn create_virtio_node<T: DeviceInfoForFdt + Clone + Debug>(
|
||||||
fdt: &mut Vec<u8>,
|
fdt: &mut FdtWriter,
|
||||||
dev_info: &T,
|
dev_info: &T,
|
||||||
) -> Result<()> {
|
) -> FdtWriterResult<()> {
|
||||||
let device_reg_prop = generate_prop64(&[dev_info.addr(), dev_info.length()]);
|
let device_reg_prop = [dev_info.addr(), dev_info.length()];
|
||||||
let irq = generate_prop32(&[GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_EDGE_RISING]);
|
let irq = [GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_EDGE_RISING];
|
||||||
|
|
||||||
append_begin_node(fdt, &format!("virtio_mmio@{:x}", dev_info.addr()))?;
|
let virtio_node = fdt.begin_node(&format!("virtio_mmio@{:x}", dev_info.addr()))?;
|
||||||
append_property_string(fdt, "compatible", "virtio,mmio")?;
|
fdt.property_string("compatible", "virtio,mmio")?;
|
||||||
append_property(fdt, "reg", &device_reg_prop)?;
|
fdt.property_array_u64("reg", &device_reg_prop)?;
|
||||||
append_property(fdt, "interrupts", &irq)?;
|
fdt.property_array_u32("interrupts", &irq)?;
|
||||||
append_property_u32(fdt, "interrupt-parent", GIC_PHANDLE)?;
|
fdt.property_u32("interrupt-parent", GIC_PHANDLE)?;
|
||||||
append_end_node(fdt)?;
|
fdt.end_node(virtio_node)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_serial_node<T: DeviceInfoForFdt + Clone + Debug>(
|
fn create_serial_node<T: DeviceInfoForFdt + Clone + Debug>(
|
||||||
fdt: &mut Vec<u8>,
|
fdt: &mut FdtWriter,
|
||||||
dev_info: &T,
|
dev_info: &T,
|
||||||
) -> Result<()> {
|
) -> FdtWriterResult<()> {
|
||||||
let compatible = b"arm,pl011\0arm,primecell\0";
|
let compatible = b"arm,pl011\0arm,primecell\0";
|
||||||
let serial_reg_prop = generate_prop64(&[dev_info.addr(), dev_info.length()]);
|
let serial_reg_prop = [dev_info.addr(), dev_info.length()];
|
||||||
let irq = generate_prop32(&[GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_EDGE_RISING]);
|
let irq = [
|
||||||
|
GIC_FDT_IRQ_TYPE_SPI,
|
||||||
|
dev_info.irq() - IRQ_BASE,
|
||||||
|
IRQ_TYPE_EDGE_RISING,
|
||||||
|
];
|
||||||
|
|
||||||
append_begin_node(fdt, &format!("pl011@{:x}", dev_info.addr()))?;
|
let serial_node = fdt.begin_node(&format!("pl011@{:x}", dev_info.addr()))?;
|
||||||
append_property(fdt, "compatible", compatible)?;
|
fdt.property("compatible", compatible)?;
|
||||||
append_property(fdt, "reg", &serial_reg_prop)?;
|
fdt.property_array_u64("reg", &serial_reg_prop)?;
|
||||||
append_property_u32(fdt, "clocks", CLOCK_PHANDLE)?;
|
fdt.property_u32("clocks", CLOCK_PHANDLE)?;
|
||||||
append_property_string(fdt, "clock-names", "apb_pclk")?;
|
fdt.property_string("clock-names", "apb_pclk")?;
|
||||||
append_property(fdt, "interrupts", &irq)?;
|
fdt.property_array_u32("interrupts", &irq)?;
|
||||||
append_end_node(fdt)?;
|
fdt.end_node(serial_node)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_rtc_node<T: DeviceInfoForFdt + Clone + Debug>(
|
fn create_rtc_node<T: DeviceInfoForFdt + Clone + Debug>(
|
||||||
fdt: &mut Vec<u8>,
|
fdt: &mut FdtWriter,
|
||||||
dev_info: &T,
|
dev_info: &T,
|
||||||
) -> Result<()> {
|
) -> FdtWriterResult<()> {
|
||||||
let compatible = b"arm,pl031\0arm,primecell\0";
|
let compatible = b"arm,pl031\0arm,primecell\0";
|
||||||
let rtc_reg_prop = generate_prop64(&[dev_info.addr(), dev_info.length()]);
|
let rtc_reg_prop = [dev_info.addr(), dev_info.length()];
|
||||||
let irq = generate_prop32(&[GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_LEVEL_HI]);
|
let irq = [
|
||||||
append_begin_node(fdt, &format!("rtc@{:x}", dev_info.addr()))?;
|
GIC_FDT_IRQ_TYPE_SPI,
|
||||||
append_property(fdt, "compatible", compatible)?;
|
dev_info.irq() - IRQ_BASE,
|
||||||
append_property(fdt, "reg", &rtc_reg_prop)?;
|
IRQ_TYPE_LEVEL_HI,
|
||||||
append_property(fdt, "interrupts", &irq)?;
|
];
|
||||||
append_property_u32(fdt, "clocks", CLOCK_PHANDLE)?;
|
|
||||||
append_property_string(fdt, "clock-names", "apb_pclk")?;
|
let rtc_node = fdt.begin_node(&format!("rtc@{:x}", dev_info.addr()))?;
|
||||||
append_end_node(fdt)?;
|
fdt.property("compatible", compatible)?;
|
||||||
|
fdt.property_array_u64("reg", &rtc_reg_prop)?;
|
||||||
|
fdt.property_array_u32("interrupts", &irq)?;
|
||||||
|
fdt.property_u32("clocks", CLOCK_PHANDLE)?;
|
||||||
|
fdt.property_string("clock-names", "apb_pclk")?;
|
||||||
|
fdt.end_node(rtc_node)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_gpio_node<T: DeviceInfoForFdt + Clone + Debug>(
|
fn create_gpio_node<T: DeviceInfoForFdt + Clone + Debug>(
|
||||||
fdt: &mut Vec<u8>,
|
fdt: &mut FdtWriter,
|
||||||
dev_info: &T,
|
dev_info: &T,
|
||||||
) -> Result<()> {
|
) -> FdtWriterResult<()> {
|
||||||
// PL061 GPIO controller node
|
// PL061 GPIO controller node
|
||||||
let compatible = b"arm,pl061\0arm,primecell\0";
|
let compatible = b"arm,pl061\0arm,primecell\0";
|
||||||
let gpio_reg_prop = generate_prop64(&[dev_info.addr(), dev_info.length()]);
|
let gpio_reg_prop = [dev_info.addr(), dev_info.length()];
|
||||||
let irq = generate_prop32(&[GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_EDGE_RISING]);
|
let irq = [
|
||||||
append_begin_node(fdt, &format!("pl061@{:x}", dev_info.addr()))?;
|
GIC_FDT_IRQ_TYPE_SPI,
|
||||||
append_property(fdt, "compatible", compatible)?;
|
dev_info.irq() - IRQ_BASE,
|
||||||
append_property(fdt, "reg", &gpio_reg_prop)?;
|
IRQ_TYPE_EDGE_RISING,
|
||||||
append_property(fdt, "interrupts", &irq)?;
|
];
|
||||||
append_property_null(fdt, "gpio-controller")?;
|
|
||||||
append_property_u32(fdt, "#gpio-cells", 2)?;
|
let gpio_node = fdt.begin_node(&format!("pl061@{:x}", dev_info.addr()))?;
|
||||||
append_property_u32(fdt, "clocks", CLOCK_PHANDLE)?;
|
fdt.property("compatible", compatible)?;
|
||||||
append_property_string(fdt, "clock-names", "apb_pclk")?;
|
fdt.property_array_u64("reg", &gpio_reg_prop)?;
|
||||||
append_property_u32(fdt, "phandle", GPIO_PHANDLE)?;
|
fdt.property_array_u32("interrupts", &irq)?;
|
||||||
append_end_node(fdt)?;
|
fdt.property_null("gpio-controller")?;
|
||||||
|
fdt.property_u32("#gpio-cells", 2)?;
|
||||||
|
fdt.property_u32("clocks", CLOCK_PHANDLE)?;
|
||||||
|
fdt.property_string("clock-names", "apb_pclk")?;
|
||||||
|
fdt.property_u32("phandle", GPIO_PHANDLE)?;
|
||||||
|
fdt.end_node(gpio_node)?;
|
||||||
|
|
||||||
// gpio-keys node
|
// gpio-keys node
|
||||||
append_begin_node(fdt, "/gpio-keys")?;
|
let gpio_keys_node = fdt.begin_node("gpio-keys")?;
|
||||||
append_property_string(fdt, "compatible", "gpio-keys")?;
|
fdt.property_string("compatible", "gpio-keys")?;
|
||||||
append_property_u32(fdt, "#size-cells", 0)?;
|
fdt.property_u32("#size-cells", 0)?;
|
||||||
append_property_u32(fdt, "#address-cells", 1)?;
|
fdt.property_u32("#address-cells", 1)?;
|
||||||
append_begin_node(fdt, "/gpio-keys/poweroff")?;
|
let gpio_keys_poweroff_node = fdt.begin_node("button@1")?;
|
||||||
append_property_string(fdt, "label", "GPIO Key Poweroff")?;
|
fdt.property_string("label", "GPIO Key Poweroff")?;
|
||||||
append_property_u32(fdt, "linux,code", KEY_POWER)?;
|
fdt.property_u32("linux,code", KEY_POWER)?;
|
||||||
let gpios = generate_prop32(&[GPIO_PHANDLE, 3, 0]);
|
let gpios = [GPIO_PHANDLE, 3, 0];
|
||||||
append_property(fdt, "gpios", &gpios)?;
|
fdt.property_array_u32("gpios", &gpios)?;
|
||||||
append_end_node(fdt)?;
|
fdt.end_node(gpio_keys_poweroff_node)?;
|
||||||
append_end_node(fdt)?;
|
fdt.end_node(gpio_keys_node)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_devices_node<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
|
fn create_devices_node<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
|
||||||
fdt: &mut Vec<u8>,
|
fdt: &mut FdtWriter,
|
||||||
dev_info: &HashMap<(DeviceType, String), T, S>,
|
dev_info: &HashMap<(DeviceType, String), T, S>,
|
||||||
) -> Result<()> {
|
) -> FdtWriterResult<()> {
|
||||||
// Create one temp Vec to store all virtio devices
|
// Create one temp Vec to store all virtio devices
|
||||||
let mut ordered_virtio_device: Vec<&T> = Vec::new();
|
let mut ordered_virtio_device: Vec<&T> = Vec::new();
|
||||||
|
|
||||||
@@ -592,11 +405,40 @@ fn create_devices_node<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::Buil
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_pci_nodes(fdt: &mut Vec<u8>, pci_device_base: u64, pci_device_size: u64) -> Result<()> {
|
fn create_pci_nodes(
|
||||||
|
fdt: &mut FdtWriter,
|
||||||
|
pci_device_base: u64,
|
||||||
|
pci_device_size: u64,
|
||||||
|
) -> FdtWriterResult<()> {
|
||||||
// Add node for PCIe controller.
|
// Add node for PCIe controller.
|
||||||
// See Documentation/devicetree/bindings/pci/host-generic-pci.txt in the kernel
|
// See Documentation/devicetree/bindings/pci/host-generic-pci.txt in the kernel
|
||||||
// and https://elinux.org/Device_Tree_Usage.
|
// and https://elinux.org/Device_Tree_Usage.
|
||||||
let ranges = generate_prop32(&[
|
|
||||||
|
// EDK2 requires the PCIe high space above 4G address.
|
||||||
|
// The actual space in CLH follows the RAM. If the RAM space is small, the PCIe high space
|
||||||
|
// could fall bellow 4G.
|
||||||
|
// Here we put it above 512G in FDT to workaround the EDK2 check.
|
||||||
|
// But the address written in ACPI is not impacted.
|
||||||
|
let pci_device_base_64bit: u64 = if cfg!(feature = "acpi") {
|
||||||
|
pci_device_base + PCI_HIGH_BASE
|
||||||
|
} else {
|
||||||
|
pci_device_base
|
||||||
|
};
|
||||||
|
let pci_device_size_64bit: u64 = if cfg!(feature = "acpi") {
|
||||||
|
pci_device_size - PCI_HIGH_BASE
|
||||||
|
} else {
|
||||||
|
pci_device_size
|
||||||
|
};
|
||||||
|
|
||||||
|
let ranges = [
|
||||||
|
// io addresses
|
||||||
|
0x1000000,
|
||||||
|
0_u32,
|
||||||
|
0_u32,
|
||||||
|
(MEM_PCI_IO_START.0 >> 32) as u32,
|
||||||
|
MEM_PCI_IO_START.0 as u32,
|
||||||
|
(MEM_PCI_IO_SIZE >> 32) as u32,
|
||||||
|
MEM_PCI_IO_SIZE as u32,
|
||||||
// mmio addresses
|
// mmio addresses
|
||||||
0x2000000, // (ss = 10: 32-bit memory space)
|
0x2000000, // (ss = 10: 32-bit memory space)
|
||||||
(MEM_32BIT_DEVICES_START.0 >> 32) as u32, // PCI address
|
(MEM_32BIT_DEVICES_START.0 >> 32) as u32, // PCI address
|
||||||
@@ -606,31 +448,31 @@ fn create_pci_nodes(fdt: &mut Vec<u8>, pci_device_base: u64, pci_device_size: u6
|
|||||||
(MEM_32BIT_DEVICES_SIZE >> 32) as u32, // size
|
(MEM_32BIT_DEVICES_SIZE >> 32) as u32, // size
|
||||||
MEM_32BIT_DEVICES_SIZE as u32,
|
MEM_32BIT_DEVICES_SIZE as u32,
|
||||||
// device addresses
|
// device addresses
|
||||||
0x3000000, // (ss = 11: 64-bit memory space)
|
0x3000000, // (ss = 11: 64-bit memory space)
|
||||||
(pci_device_base >> 32) as u32, // PCI address
|
(pci_device_base_64bit >> 32) as u32, // PCI address
|
||||||
pci_device_base as u32,
|
pci_device_base_64bit as u32,
|
||||||
(pci_device_base >> 32) as u32, // CPU address
|
(pci_device_base_64bit >> 32) as u32, // CPU address
|
||||||
pci_device_base as u32,
|
pci_device_base_64bit as u32,
|
||||||
(pci_device_size >> 32) as u32, // size
|
(pci_device_size_64bit >> 32) as u32, // size
|
||||||
pci_device_size as u32,
|
pci_device_size_64bit as u32,
|
||||||
]);
|
];
|
||||||
let bus_range = generate_prop32(&[0, 0]); // Only bus 0
|
let bus_range = [0, 0]; // Only bus 0
|
||||||
let reg = generate_prop64(&[PCI_MMCONFIG_START.0, PCI_MMCONFIG_SIZE]);
|
let reg = [PCI_MMCONFIG_START.0, PCI_MMCONFIG_SIZE];
|
||||||
|
|
||||||
append_begin_node(fdt, "pci")?;
|
let pci_node = fdt.begin_node("pci")?;
|
||||||
append_property_string(fdt, "compatible", "pci-host-ecam-generic")?;
|
fdt.property_string("compatible", "pci-host-ecam-generic")?;
|
||||||
append_property_string(fdt, "device_type", "pci")?;
|
fdt.property_string("device_type", "pci")?;
|
||||||
append_property(fdt, "ranges", &ranges)?;
|
fdt.property_array_u32("ranges", &ranges)?;
|
||||||
append_property(fdt, "bus-range", &bus_range)?;
|
fdt.property_array_u32("bus-range", &bus_range)?;
|
||||||
append_property_u32(fdt, "#address-cells", 3)?;
|
fdt.property_u32("#address-cells", 3)?;
|
||||||
append_property_u32(fdt, "#size-cells", 2)?;
|
fdt.property_u32("#size-cells", 2)?;
|
||||||
append_property(fdt, "reg", ®)?;
|
fdt.property_array_u64("reg", ®)?;
|
||||||
append_property_u32(fdt, "#interrupt-cells", 1)?;
|
fdt.property_u32("#interrupt-cells", 1)?;
|
||||||
append_property_null(fdt, "interrupt-map")?;
|
fdt.property_null("interrupt-map")?;
|
||||||
append_property_null(fdt, "interrupt-map-mask")?;
|
fdt.property_null("interrupt-map-mask")?;
|
||||||
append_property_null(fdt, "dma-coherent")?;
|
fdt.property_null("dma-coherent")?;
|
||||||
append_property_u32(fdt, "msi-parent", MSI_PHANDLE)?;
|
fdt.property_u32("msi-parent", MSI_PHANDLE)?;
|
||||||
append_end_node(fdt)?;
|
fdt.end_node(pci_node)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,17 +5,23 @@ pub mod kvm {
|
|||||||
use crate::aarch64::gic::dist_regs::{get_dist_regs, read_ctlr, set_dist_regs, write_ctlr};
|
use crate::aarch64::gic::dist_regs::{get_dist_regs, read_ctlr, set_dist_regs, write_ctlr};
|
||||||
use crate::aarch64::gic::icc_regs::{get_icc_regs, set_icc_regs};
|
use crate::aarch64::gic::icc_regs::{get_icc_regs, set_icc_regs};
|
||||||
use crate::aarch64::gic::kvm::{save_pending_tables, KvmGicDevice};
|
use crate::aarch64::gic::kvm::{save_pending_tables, KvmGicDevice};
|
||||||
use crate::aarch64::gic::redist_regs::{get_redist_regs, set_redist_regs};
|
use crate::aarch64::gic::redist_regs::{
|
||||||
|
construct_gicr_typers, get_redist_regs, set_redist_regs,
|
||||||
|
};
|
||||||
use crate::aarch64::gic::GicDevice;
|
use crate::aarch64::gic::GicDevice;
|
||||||
use crate::layout;
|
use crate::layout;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use hypervisor::kvm::kvm_bindings;
|
use hypervisor::kvm::kvm_bindings;
|
||||||
|
use hypervisor::CpuState;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{boxed::Box, result};
|
use std::{boxed::Box, result};
|
||||||
|
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||||
|
use versionize_derive::Versionize;
|
||||||
use vm_migration::{
|
use vm_migration::{
|
||||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable,
|
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable,
|
||||||
|
VersionMapped,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Errors thrown while saving/restoring the GICv3.
|
/// Errors thrown while saving/restoring the GICv3.
|
||||||
@@ -57,7 +63,7 @@ pub mod kvm {
|
|||||||
vcpu_count: u64,
|
vcpu_count: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Versionize)]
|
||||||
pub struct Gicv3State {
|
pub struct Gicv3State {
|
||||||
dist: Vec<u32>,
|
dist: Vec<u32>,
|
||||||
rdist: Vec<u32>,
|
rdist: Vec<u32>,
|
||||||
@@ -66,6 +72,8 @@ pub mod kvm {
|
|||||||
gicd_ctlr: u32,
|
gicd_ctlr: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl VersionMapped for Gicv3State {}
|
||||||
|
|
||||||
impl KvmGicV3 {
|
impl KvmGicV3 {
|
||||||
// Unfortunately bindgen omits defines that are based on other defines.
|
// Unfortunately bindgen omits defines that are based on other defines.
|
||||||
// See arch/arm64/include/uapi/asm/kvm.h file from the linux kernel.
|
// See arch/arm64/include/uapi/asm/kvm.h file from the linux kernel.
|
||||||
@@ -160,7 +168,8 @@ pub mod kvm {
|
|||||||
self.vcpu_count
|
self.vcpu_count
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_gicr_typers(&mut self, gicr_typers: Vec<u64>) {
|
fn set_gicr_typers(&mut self, vcpu_states: &[CpuState]) {
|
||||||
|
let gicr_typers = construct_gicr_typers(vcpu_states);
|
||||||
self.gicr_typers = gicr_typers;
|
self.gicr_typers = gicr_typers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,12 +238,12 @@ pub mod kvm {
|
|||||||
|
|
||||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||||
let gicr_typers = self.gicr_typers.clone();
|
let gicr_typers = self.gicr_typers.clone();
|
||||||
Snapshot::new_from_state(&self.id(), &self.state(&gicr_typers).unwrap())
|
Snapshot::new_from_versioned_state(&self.id(), &self.state(&gicr_typers).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
|
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
|
||||||
let gicr_typers = self.gicr_typers.clone();
|
let gicr_typers = self.gicr_typers.clone();
|
||||||
self.set_state(&gicr_typers, &snapshot.to_state(&self.id())?)
|
self.set_state(&gicr_typers, &snapshot.to_versioned_state(&self.id())?)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
MigratableError::Restore(anyhow!("Could not restore GICv3 state {:?}", e))
|
MigratableError::Restore(anyhow!("Could not restore GICv3 state {:?}", e))
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pub mod kvm {
|
|||||||
use crate::aarch64::gic::kvm::KvmGicDevice;
|
use crate::aarch64::gic::kvm::KvmGicDevice;
|
||||||
use crate::aarch64::gic::{Error, GicDevice};
|
use crate::aarch64::gic::{Error, GicDevice};
|
||||||
use hypervisor::kvm::kvm_bindings;
|
use hypervisor::kvm::kvm_bindings;
|
||||||
|
use hypervisor::CpuState;
|
||||||
|
|
||||||
pub struct KvmGicV3Its {
|
pub struct KvmGicV3Its {
|
||||||
/// The hypervisor agnostic device
|
/// The hypervisor agnostic device
|
||||||
@@ -70,7 +71,7 @@ pub mod kvm {
|
|||||||
self.vcpu_count
|
self.vcpu_count
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_gicr_typers(&mut self, _gicr_typers: Vec<u64>) {}
|
fn set_gicr_typers(&mut self, _vcpu_states: &[CpuState]) {}
|
||||||
|
|
||||||
fn as_any_concrete_mut(&mut self) -> &mut dyn Any {
|
fn as_any_concrete_mut(&mut self) -> &mut dyn Any {
|
||||||
self
|
self
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pub mod redist_regs;
|
|||||||
pub use self::dist_regs::{get_dist_regs, read_ctlr, set_dist_regs, write_ctlr};
|
pub use self::dist_regs::{get_dist_regs, read_ctlr, set_dist_regs, write_ctlr};
|
||||||
pub use self::icc_regs::{get_icc_regs, set_icc_regs};
|
pub use self::icc_regs::{get_icc_regs, set_icc_regs};
|
||||||
pub use self::redist_regs::{get_redist_regs, set_redist_regs};
|
pub use self::redist_regs::{get_redist_regs, set_redist_regs};
|
||||||
|
use hypervisor::CpuState;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -58,7 +59,7 @@ pub trait GicDevice: Send {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the values of GICR_TYPER for each vCPU.
|
/// Get the values of GICR_TYPER for each vCPU.
|
||||||
fn set_gicr_typers(&mut self, gicr_typers: Vec<u64>);
|
fn set_gicr_typers(&mut self, vcpu_states: &[CpuState]);
|
||||||
|
|
||||||
/// Downcast the trait object to its concrete type.
|
/// Downcast the trait object to its concrete type.
|
||||||
fn as_any_concrete_mut(&mut self) -> &mut dyn Any;
|
fn as_any_concrete_mut(&mut self) -> &mut dyn Any;
|
||||||
@@ -149,7 +150,7 @@ pub mod kvm {
|
|||||||
/* We need to tell the kernel how many irqs to support with this vgic.
|
/* We need to tell the kernel how many irqs to support with this vgic.
|
||||||
* See the `layout` module for details.
|
* See the `layout` module for details.
|
||||||
*/
|
*/
|
||||||
let nr_irqs: u32 = layout::IRQ_MAX - layout::IRQ_BASE + 1;
|
let nr_irqs: u32 = layout::IRQ_NUM;
|
||||||
let nr_irqs_ptr = &nr_irqs as *const u32;
|
let nr_irqs_ptr = &nr_irqs as *const u32;
|
||||||
Self::set_device_attribute(
|
Self::set_device_attribute(
|
||||||
gic_device.device(),
|
gic_device.device(),
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
use super::{Error, Result};
|
use super::{Error, Result};
|
||||||
use hypervisor::kvm::kvm_bindings::{kvm_device_attr, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS};
|
use hypervisor::kvm::kvm_bindings::{kvm_device_attr, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS};
|
||||||
|
use hypervisor::CpuState;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
// Relevant redistributor registers that we want to save/restore.
|
// Relevant redistributor registers that we want to save/restore.
|
||||||
@@ -177,3 +178,34 @@ pub fn set_redist_regs(
|
|||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn construct_gicr_typers(vcpu_states: &[CpuState]) -> Vec<u64> {
|
||||||
|
/* Pre-construct the GICR_TYPER:
|
||||||
|
* For our implementation:
|
||||||
|
* Top 32 bits are the affinity value of the associated CPU
|
||||||
|
* CommonLPIAff == 01 (redistributors with same Aff3 share LPI table)
|
||||||
|
* Processor_Number == CPU index starting from 0
|
||||||
|
* DPGS == 0 (GICR_CTLR.DPG* not supported)
|
||||||
|
* Last == 1 if this is the last redistributor in a series of
|
||||||
|
* contiguous redistributor pages
|
||||||
|
* DirectLPI == 0 (direct injection of LPIs not supported)
|
||||||
|
* VLPIS == 0 (virtual LPIs not supported)
|
||||||
|
* PLPIS == 0 (physical LPIs not supported)
|
||||||
|
*/
|
||||||
|
let mut gicr_typers: Vec<u64> = Vec::new();
|
||||||
|
for (index, state) in vcpu_states.iter().enumerate() {
|
||||||
|
let last = {
|
||||||
|
if index == vcpu_states.len() - 1 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//calculate affinity
|
||||||
|
let mut cpu_affid = state.mpidr & 1095233437695;
|
||||||
|
cpu_affid = ((cpu_affid & 0xFF00000000) >> 8) | (cpu_affid & 0xFFFFFF);
|
||||||
|
gicr_typers.push((cpu_affid << 32) | (1 << 24) | (index as u64) << 8 | (last << 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
gicr_typers
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
// | |
|
// | |
|
||||||
// 144 M +---------------------------------------------------------------|
|
// 144 M +---------------------------------------------------------------|
|
||||||
// | Reserved (now GIC is here) |
|
// | Reserved (now GIC is here) |
|
||||||
// 128 M +---------------------------------------------------------------+
|
// 64 M +---------------------------------------------------------------+
|
||||||
// | |
|
// | |
|
||||||
// | UEFI space |
|
// | UEFI space |
|
||||||
// | |
|
// | |
|
||||||
@@ -46,26 +46,23 @@
|
|||||||
|
|
||||||
use vm_memory::GuestAddress;
|
use vm_memory::GuestAddress;
|
||||||
|
|
||||||
/// 0x0 ~ 0x800_0000 is reserved to uefi
|
/// 0x0 ~ 0x400_0000 is reserved to uefi
|
||||||
pub const UEFI_START: u64 = 0x0;
|
pub const UEFI_START: u64 = 0x0;
|
||||||
pub const MEM_UEFI_START: GuestAddress = GuestAddress(0);
|
pub const MEM_UEFI_START: GuestAddress = GuestAddress(0);
|
||||||
pub const UEFI_SIZE: u64 = 0x0800_0000;
|
pub const UEFI_SIZE: u64 = 0x0400_0000;
|
||||||
|
|
||||||
/// Below this address will reside the GIC, above this address will reside the MMIO devices.
|
/// Below this address will reside the GIC, above this address will reside the MMIO devices.
|
||||||
pub const MAPPED_IO_START: u64 = 0x0900_0000;
|
pub const MAPPED_IO_START: u64 = 0x0900_0000;
|
||||||
|
|
||||||
/// Space 0x0900_0000 ~ 0x1000_0000 is reserved for legacy devices.
|
/// Space 0x0900_0000 ~ 0x0905_0000 is reserved for legacy devices.
|
||||||
pub const LEGACY_SERIAL_MAPPED_IO_START: u64 = 0x0900_0000;
|
pub const LEGACY_SERIAL_MAPPED_IO_START: u64 = 0x0900_0000;
|
||||||
pub const LEGACY_RTC_MAPPED_IO_START: u64 = 0x0901_0000;
|
pub const LEGACY_RTC_MAPPED_IO_START: u64 = 0x0901_0000;
|
||||||
pub const LEGACY_GPIO_MAPPED_IO_START: u64 = 0x0902_0000;
|
pub const LEGACY_GPIO_MAPPED_IO_START: u64 = 0x0902_0000;
|
||||||
|
|
||||||
/// Space 0x0902_0000 ~ 0x903_0000 is reserved for pcie io address
|
/// Space 0x0905_0000 ~ 0x0906_0000 is reserved for pcie io address
|
||||||
pub const MEM_PCI_IO_START: GuestAddress = GuestAddress(0x0902_0000);
|
pub const MEM_PCI_IO_START: GuestAddress = GuestAddress(0x0905_0000);
|
||||||
pub const MEM_PCI_IO_SIZE: u64 = 0x10000;
|
pub const MEM_PCI_IO_SIZE: u64 = 0x10000;
|
||||||
|
|
||||||
/// Legacy space will be allocated at once whiling setting up legacy devices.
|
|
||||||
pub const LEGACY_DEVICES_MAPPED_IO_SIZE: u64 = 0x0700_0000;
|
|
||||||
|
|
||||||
/// Starting from 0x1000_0000 (256MiB) to 0x3000_0000 (768MiB) is used for PCIE MMIO
|
/// Starting from 0x1000_0000 (256MiB) to 0x3000_0000 (768MiB) is used for PCIE MMIO
|
||||||
pub const MEM_32BIT_DEVICES_START: GuestAddress = GuestAddress(0x1000_0000);
|
pub const MEM_32BIT_DEVICES_START: GuestAddress = GuestAddress(0x1000_0000);
|
||||||
pub const MEM_32BIT_DEVICES_SIZE: u64 = 0x2000_0000;
|
pub const MEM_32BIT_DEVICES_SIZE: u64 = 0x2000_0000;
|
||||||
@@ -81,21 +78,30 @@ pub const RAM_64BIT_START: u64 = 0x4000_0000;
|
|||||||
/// As per `arch/arm64/include/uapi/asm/setup.h`.
|
/// As per `arch/arm64/include/uapi/asm/setup.h`.
|
||||||
pub const CMDLINE_MAX_SIZE: usize = 2048;
|
pub const CMDLINE_MAX_SIZE: usize = 2048;
|
||||||
|
|
||||||
|
/// FDT is at the beginning of RAM.
|
||||||
/// Maximum size of the device tree blob as specified in https://www.kernel.org/doc/Documentation/arm64/booting.txt.
|
/// Maximum size of the device tree blob as specified in https://www.kernel.org/doc/Documentation/arm64/booting.txt.
|
||||||
|
pub const FDT_START: u64 = RAM_64BIT_START;
|
||||||
pub const FDT_MAX_SIZE: usize = 0x20_0000;
|
pub const FDT_MAX_SIZE: usize = 0x20_0000;
|
||||||
|
|
||||||
/// Put ACPI table above dtb
|
/// Put ACPI table above dtb
|
||||||
pub const ACPI_START: u64 = RAM_64BIT_START + FDT_MAX_SIZE as u64;
|
pub const ACPI_START: u64 = RAM_64BIT_START + FDT_MAX_SIZE as u64;
|
||||||
|
pub const ACPI_MAX_SIZE: usize = 0x20_0000;
|
||||||
pub const RSDP_POINTER: GuestAddress = GuestAddress(ACPI_START);
|
pub const RSDP_POINTER: GuestAddress = GuestAddress(ACPI_START);
|
||||||
|
|
||||||
|
/// Kernel start after FDT and ACPI
|
||||||
|
pub const KERNEL_START: u64 = ACPI_START + ACPI_MAX_SIZE as u64;
|
||||||
|
|
||||||
|
/// Pci high memory base
|
||||||
|
pub const PCI_HIGH_BASE: u64 = 0x80_0000_0000_u64;
|
||||||
|
|
||||||
// As per virt/kvm/arm/vgic/vgic-kvm-device.c we need
|
// As per virt/kvm/arm/vgic/vgic-kvm-device.c we need
|
||||||
// the number of interrupts our GIC will support to be:
|
// the number of interrupts our GIC will support to be:
|
||||||
// * bigger than 32
|
// * bigger than 32
|
||||||
// * less than 1023 and
|
// * less than 1023 and
|
||||||
// * a multiple of 32.
|
// * a multiple of 32.
|
||||||
// We are setting up our interrupt controller to support a maximum of 256 interrupts.
|
// We are setting up our interrupt controller to support a maximum of 256 interrupts.
|
||||||
/// First usable interrupt on aarch64.
|
/// First usable interrupt on aarch64
|
||||||
pub const IRQ_BASE: u32 = 0;
|
pub const IRQ_BASE: u32 = 32;
|
||||||
|
|
||||||
/// Last usable interrupt on aarch64.
|
/// Number of supported interrupts
|
||||||
pub const IRQ_MAX: u32 = 255;
|
pub const IRQ_NUM: u32 = 256;
|
||||||
|
|||||||
@@ -10,25 +10,31 @@ pub mod gic;
|
|||||||
pub mod layout;
|
pub mod layout;
|
||||||
/// Logic for configuring aarch64 registers.
|
/// Logic for configuring aarch64 registers.
|
||||||
pub mod regs;
|
pub mod regs;
|
||||||
|
/// Module for loading UEFI binary.
|
||||||
|
pub mod uefi;
|
||||||
|
|
||||||
pub use self::fdt::DeviceInfoForFdt;
|
pub use self::fdt::DeviceInfoForFdt;
|
||||||
use crate::DeviceType;
|
use crate::DeviceType;
|
||||||
|
use crate::GuestMemoryMmap;
|
||||||
use crate::RegionType;
|
use crate::RegionType;
|
||||||
use aarch64::gic::GicDevice;
|
use gic::GicDevice;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::convert::TryInto;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vm_memory::{
|
use vm_memory::{
|
||||||
Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, GuestMemoryMmap,
|
Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, GuestUsize,
|
||||||
GuestUsize,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Errors thrown while configuring aarch64 system.
|
/// Errors thrown while configuring aarch64 system.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Failed to create a FDT.
|
/// Failed to create a FDT.
|
||||||
SetupFdt(fdt::Error),
|
SetupFdt,
|
||||||
|
|
||||||
|
/// Failed to write FDT to memory.
|
||||||
|
WriteFdtToMemory(fdt::Error),
|
||||||
|
|
||||||
/// Failed to create a GIC.
|
/// Failed to create a GIC.
|
||||||
SetupGic(gic::Error),
|
SetupGic(gic::Error),
|
||||||
@@ -79,64 +85,78 @@ pub fn configure_vcpu(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
|
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
|
||||||
|
// Normally UEFI should be loaded to a flash area at the beginning of memory.
|
||||||
|
// But now flash memory type is not supported.
|
||||||
|
// As a workaround, we take 64 MiB memory from the main RAM for UEFI.
|
||||||
|
// As a result, the RAM that the guest can see is less than what has been
|
||||||
|
// assigned in command line, when ACPI and UEFI is enabled.
|
||||||
|
let ram_deduction = if cfg!(feature = "acpi") {
|
||||||
|
layout::UEFI_SIZE
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
vec![
|
vec![
|
||||||
// 0 ~ 256 MiB: Reserved
|
// 0 ~ 64 MiB: Reserved for UEFI space
|
||||||
|
#[cfg(feature = "acpi")]
|
||||||
|
(GuestAddress(0), layout::UEFI_SIZE as usize, RegionType::Ram),
|
||||||
|
#[cfg(not(feature = "acpi"))]
|
||||||
(
|
(
|
||||||
GuestAddress(0),
|
GuestAddress(0),
|
||||||
layout::MEM_32BIT_DEVICES_START.0 as usize,
|
layout::UEFI_SIZE as usize,
|
||||||
RegionType::Reserved,
|
RegionType::Reserved,
|
||||||
),
|
),
|
||||||
// 256 MiB ~ 1 G: MMIO space
|
// 64 MiB ~ 256 MiB: Gic and legacy devices
|
||||||
|
(
|
||||||
|
GuestAddress(layout::UEFI_SIZE),
|
||||||
|
(layout::MEM_32BIT_DEVICES_START.0 - layout::UEFI_SIZE) as usize,
|
||||||
|
RegionType::Reserved,
|
||||||
|
),
|
||||||
|
// 256 MiB ~ 768 MiB: MMIO space
|
||||||
(
|
(
|
||||||
layout::MEM_32BIT_DEVICES_START,
|
layout::MEM_32BIT_DEVICES_START,
|
||||||
layout::MEM_32BIT_DEVICES_SIZE as usize,
|
layout::MEM_32BIT_DEVICES_SIZE as usize,
|
||||||
RegionType::SubRegion,
|
RegionType::SubRegion,
|
||||||
),
|
),
|
||||||
// 1G ~ 2G: reserved. The leading 256M for PCIe MMCONFIG space
|
// 768 MiB ~ 1 GiB: reserved. The leading 256M for PCIe MMCONFIG space
|
||||||
(
|
(
|
||||||
layout::PCI_MMCONFIG_START,
|
layout::PCI_MMCONFIG_START,
|
||||||
(layout::RAM_64BIT_START - layout::PCI_MMCONFIG_START.0) as usize,
|
layout::PCI_MMCONFIG_SIZE as usize,
|
||||||
RegionType::Reserved,
|
RegionType::Reserved,
|
||||||
),
|
),
|
||||||
|
// 1 GiB ~ : Ram
|
||||||
(
|
(
|
||||||
GuestAddress(layout::RAM_64BIT_START),
|
GuestAddress(layout::RAM_64BIT_START),
|
||||||
size as usize,
|
(size - ram_deduction) as usize,
|
||||||
RegionType::Ram,
|
RegionType::Ram,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configures the system and should be called once per vm before starting vcpu threads.
|
/// Configures the system and should be called once per vm before starting vcpu threads.
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `guest_mem` - The memory to be used by the guest.
|
|
||||||
/// * `num_cpus` - Number of virtual CPUs the guest will have.
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
pub fn configure_system<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
|
pub fn configure_system<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
|
||||||
vm: &Arc<dyn hypervisor::Vm>,
|
|
||||||
guest_mem: &GuestMemoryMmap,
|
guest_mem: &GuestMemoryMmap,
|
||||||
cmdline_cstring: &CStr,
|
cmdline_cstring: &CStr,
|
||||||
vcpu_count: u64,
|
|
||||||
vcpu_mpidr: Vec<u64>,
|
vcpu_mpidr: Vec<u64>,
|
||||||
device_info: &HashMap<(DeviceType, String), T, S>,
|
device_info: &HashMap<(DeviceType, String), T, S>,
|
||||||
initrd: &Option<super::InitramfsConfig>,
|
initrd: &Option<super::InitramfsConfig>,
|
||||||
pci_space_address: &(u64, u64),
|
pci_space_address: &(u64, u64),
|
||||||
) -> super::Result<Box<dyn GicDevice>> {
|
gic_device: &dyn GicDevice,
|
||||||
let gic_device = gic::kvm::create_gic(vm, vcpu_count).map_err(Error::SetupGic)?;
|
) -> super::Result<()> {
|
||||||
|
let fdt_final = fdt::create_fdt(
|
||||||
fdt::create_fdt(
|
|
||||||
guest_mem,
|
guest_mem,
|
||||||
cmdline_cstring,
|
cmdline_cstring,
|
||||||
vcpu_mpidr,
|
vcpu_mpidr,
|
||||||
device_info,
|
device_info,
|
||||||
&*gic_device,
|
gic_device,
|
||||||
initrd,
|
initrd,
|
||||||
pci_space_address,
|
pci_space_address,
|
||||||
)
|
)
|
||||||
.map_err(Error::SetupFdt)?;
|
.map_err(|_| Error::SetupFdt)?;
|
||||||
|
|
||||||
Ok(gic_device)
|
fdt::write_fdt_to_memory(fdt_final, guest_mem).map_err(Error::WriteFdtToMemory)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the memory address where the initramfs could be loaded.
|
/// Returns the memory address where the initramfs could be loaded.
|
||||||
@@ -145,8 +165,9 @@ pub fn initramfs_load_addr(
|
|||||||
initramfs_size: usize,
|
initramfs_size: usize,
|
||||||
) -> super::Result<u64> {
|
) -> super::Result<u64> {
|
||||||
let round_to_pagesize = |size| (size + (super::PAGE_SIZE - 1)) & !(super::PAGE_SIZE - 1);
|
let round_to_pagesize = |size| (size + (super::PAGE_SIZE - 1)) & !(super::PAGE_SIZE - 1);
|
||||||
match GuestAddress(get_fdt_addr(&guest_mem))
|
match guest_mem
|
||||||
.checked_sub(round_to_pagesize(initramfs_size) as u64)
|
.last_addr()
|
||||||
|
.checked_sub(round_to_pagesize(initramfs_size) as u64 - 1)
|
||||||
{
|
{
|
||||||
Some(offset) => {
|
Some(offset) => {
|
||||||
if guest_mem.address_in_range(offset) {
|
if guest_mem.address_in_range(offset) {
|
||||||
@@ -161,41 +182,31 @@ pub fn initramfs_load_addr(
|
|||||||
|
|
||||||
/// Returns the memory address where the kernel could be loaded.
|
/// Returns the memory address where the kernel could be loaded.
|
||||||
pub fn get_kernel_start() -> u64 {
|
pub fn get_kernel_start() -> u64 {
|
||||||
layout::RAM_64BIT_START
|
layout::KERNEL_START
|
||||||
|
}
|
||||||
|
|
||||||
|
///Return guest memory address where the uefi should be loaded.
|
||||||
|
pub fn get_uefi_start() -> u64 {
|
||||||
|
layout::UEFI_START
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auxiliary function to get the address where the device tree blob is loaded.
|
// Auxiliary function to get the address where the device tree blob is loaded.
|
||||||
fn get_fdt_addr(mem: &GuestMemoryMmap) -> u64 {
|
fn get_fdt_addr() -> u64 {
|
||||||
// If the memory allocated is smaller than the size allocated for the FDT,
|
layout::FDT_START
|
||||||
// we return the start of the DRAM so that
|
|
||||||
// we allow the code to try and load the FDT.
|
|
||||||
|
|
||||||
if let Some(addr) = mem.last_addr().checked_sub(layout::FDT_MAX_SIZE as u64 - 1) {
|
|
||||||
if mem.address_in_range(addr) {
|
|
||||||
return addr.raw_value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
layout::RAM_64BIT_START
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_host_cpu_phys_bits() -> u8 {
|
pub fn get_host_cpu_phys_bits() -> u8 {
|
||||||
// The value returned here is used to determine the physical address space size
|
// A dummy hypervisor created only for querying the host IPA size and will
|
||||||
// for a VM (IPA size).
|
// be freed after the query.
|
||||||
// In recent kernel versions, the maximum IPA size supported by the host can be
|
let hv = hypervisor::new().unwrap();
|
||||||
// known by querying cap KVM_CAP_ARM_VM_IPA_SIZE. And the IPA size for a
|
let host_cpu_phys_bits = hv.get_host_ipa_limit().try_into().unwrap();
|
||||||
// guest can be configured smaller.
|
if host_cpu_phys_bits == 0 {
|
||||||
// But in Cloud-Hypervisor we simply use the maximum value for the VM.
|
// Host kernel does not support `get_host_ipa_limit`,
|
||||||
// Reference https://lwn.net/Articles/766767/.
|
// we return the default value 40 here.
|
||||||
//
|
40
|
||||||
// The correct way to query KVM_CAP_ARM_VM_IPA_SIZE is via rust-vmm/kvm-ioctls,
|
} else {
|
||||||
// which wraps all IOCTL's and provides easy interface to user hypervisors.
|
host_cpu_phys_bits
|
||||||
// For now the cap hasn't been supported. A separate patch will be submitted to
|
}
|
||||||
// rust-vmm to add it.
|
|
||||||
// So a hardcoded value is used here as a temporary solution.
|
|
||||||
// It will be replace once rust-vmm/kvm-ioctls is ready.
|
|
||||||
//
|
|
||||||
40
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -205,38 +216,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_arch_memory_regions_dram() {
|
fn test_arch_memory_regions_dram() {
|
||||||
let regions = arch_memory_regions((1usize << 32) as u64); //4GB
|
let regions = arch_memory_regions((1usize << 32) as u64); //4GB
|
||||||
assert_eq!(4, regions.len());
|
assert_eq!(5, regions.len());
|
||||||
assert_eq!(GuestAddress(layout::RAM_64BIT_START), regions[3].0);
|
assert_eq!(GuestAddress(layout::RAM_64BIT_START), regions[4].0);
|
||||||
assert_eq!(1usize << 32, regions[3].1);
|
assert_eq!(1usize << 32, regions[4].1);
|
||||||
assert_eq!(RegionType::Ram, regions[3].2);
|
assert_eq!(RegionType::Ram, regions[4].2);
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_get_fdt_addr() {
|
|
||||||
let mut regions = Vec::new();
|
|
||||||
|
|
||||||
regions.push((
|
|
||||||
GuestAddress(layout::RAM_64BIT_START),
|
|
||||||
(layout::FDT_MAX_SIZE - 0x1000) as usize,
|
|
||||||
));
|
|
||||||
let mem = GuestMemoryMmap::from_ranges(®ions).expect("Cannot initialize memory");
|
|
||||||
assert_eq!(get_fdt_addr(&mem), layout::RAM_64BIT_START);
|
|
||||||
regions.clear();
|
|
||||||
|
|
||||||
regions.push((
|
|
||||||
GuestAddress(layout::RAM_64BIT_START),
|
|
||||||
(layout::FDT_MAX_SIZE) as usize,
|
|
||||||
));
|
|
||||||
let mem = GuestMemoryMmap::from_ranges(®ions).expect("Cannot initialize memory");
|
|
||||||
assert_eq!(get_fdt_addr(&mem), layout::RAM_64BIT_START);
|
|
||||||
regions.clear();
|
|
||||||
|
|
||||||
regions.push((
|
|
||||||
GuestAddress(layout::RAM_64BIT_START),
|
|
||||||
(layout::FDT_MAX_SIZE + 0x1000) as usize,
|
|
||||||
));
|
|
||||||
let mem = GuestMemoryMmap::from_ranges(®ions).expect("Cannot initialize memory");
|
|
||||||
assert_eq!(get_fdt_addr(&mem), 0x1000 + layout::RAM_64BIT_START);
|
|
||||||
regions.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,13 @@
|
|||||||
// found in the THIRD-PARTY file.
|
// found in the THIRD-PARTY file.
|
||||||
|
|
||||||
use super::get_fdt_addr;
|
use super::get_fdt_addr;
|
||||||
|
use crate::GuestMemoryMmap;
|
||||||
use hypervisor::kvm::kvm_bindings::{
|
use hypervisor::kvm::kvm_bindings::{
|
||||||
kvm_regs, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
|
kvm_regs, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
|
||||||
};
|
};
|
||||||
use hypervisor::{arm64_core_reg_id, offset__of};
|
use hypervisor::{arm64_core_reg_id, offset__of};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{mem, result};
|
use std::{mem, result};
|
||||||
use vm_memory::GuestMemoryMmap;
|
|
||||||
|
|
||||||
/// Errors thrown while setting aarch64 registers.
|
/// Errors thrown while setting aarch64 registers.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -47,7 +47,7 @@ pub fn setup_regs(
|
|||||||
vcpu: &Arc<dyn hypervisor::Vcpu>,
|
vcpu: &Arc<dyn hypervisor::Vcpu>,
|
||||||
cpu_id: u8,
|
cpu_id: u8,
|
||||||
boot_ip: u64,
|
boot_ip: u64,
|
||||||
mem: &GuestMemoryMmap,
|
_mem: &GuestMemoryMmap,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let kreg_off = offset__of!(kvm_regs, regs);
|
let kreg_off = offset__of!(kvm_regs, regs);
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ pub fn setup_regs(
|
|||||||
let regs0 = offset__of!(user_pt_regs, regs) + kreg_off;
|
let regs0 = offset__of!(user_pt_regs, regs) + kreg_off;
|
||||||
vcpu.set_reg(
|
vcpu.set_reg(
|
||||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0),
|
arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0),
|
||||||
get_fdt_addr(mem) as u64,
|
get_fdt_addr() as u64,
|
||||||
)
|
)
|
||||||
.map_err(Error::SetCoreRegister)?;
|
.map_err(Error::SetCoreRegister)?;
|
||||||
}
|
}
|
||||||
|
|||||||
43
arch/src/aarch64/uefi.rs
Normal file
43
arch/src/aarch64/uefi.rs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// Copyright 2020 Arm Limited (or its affiliates). All rights reserved.
|
||||||
|
|
||||||
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
use std::result;
|
||||||
|
use vm_memory::{Bytes, GuestAddress, GuestMemory};
|
||||||
|
|
||||||
|
/// Errors thrown while loading UEFI binary
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
/// Unable to seek to UEFI image start.
|
||||||
|
SeekUefiStart,
|
||||||
|
/// Unable to seek to UEFI image end.
|
||||||
|
SeekUefiEnd,
|
||||||
|
/// UEFI image too big.
|
||||||
|
UefiTooBig,
|
||||||
|
/// Unable to read UEFI image
|
||||||
|
ReadUefiImage,
|
||||||
|
}
|
||||||
|
type Result<T> = result::Result<T, Error>;
|
||||||
|
|
||||||
|
pub fn load_uefi<F, M: GuestMemory>(
|
||||||
|
guest_mem: &M,
|
||||||
|
guest_addr: GuestAddress,
|
||||||
|
uefi_image: &mut F,
|
||||||
|
) -> Result<()>
|
||||||
|
where
|
||||||
|
F: Read + Seek,
|
||||||
|
{
|
||||||
|
let uefi_size = uefi_image
|
||||||
|
.seek(SeekFrom::End(0))
|
||||||
|
.map_err(|_| Error::SeekUefiEnd)? as usize;
|
||||||
|
|
||||||
|
// edk2 image on virtual platform is smaller than 3M
|
||||||
|
if uefi_size > 0x300000 {
|
||||||
|
return Err(Error::UefiTooBig);
|
||||||
|
}
|
||||||
|
uefi_image
|
||||||
|
.seek(SeekFrom::Start(0))
|
||||||
|
.map_err(|_| Error::SeekUefiStart)?;
|
||||||
|
guest_mem
|
||||||
|
.read_exact_from(guest_addr, uefi_image, uefi_size)
|
||||||
|
.map_err(|_| Error::ReadUefiImage)
|
||||||
|
}
|
||||||
@@ -8,28 +8,14 @@
|
|||||||
//! Supported platforms: x86_64, aarch64.
|
//! Supported platforms: x86_64, aarch64.
|
||||||
#![allow(clippy::transmute_ptr_to_ptr, clippy::redundant_static_lifetimes)]
|
#![allow(clippy::transmute_ptr_to_ptr, clippy::redundant_static_lifetimes)]
|
||||||
|
|
||||||
extern crate anyhow;
|
|
||||||
extern crate byteorder;
|
|
||||||
extern crate hypervisor;
|
|
||||||
extern crate libc;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
#[cfg(feature = "acpi")]
|
|
||||||
extern crate acpi_tables;
|
|
||||||
extern crate arch_gen;
|
|
||||||
extern crate linux_loader;
|
|
||||||
extern crate serde;
|
|
||||||
extern crate vm_memory;
|
|
||||||
extern crate vm_migration;
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
|
||||||
#[macro_use]
|
|
||||||
extern crate serde_derive;
|
|
||||||
extern crate serde_json;
|
|
||||||
extern crate thiserror;
|
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::result;
|
use std::result;
|
||||||
|
|
||||||
|
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<vm_memory::bitmap::AtomicBitmap>;
|
||||||
|
|
||||||
/// Type for returning error code.
|
/// Type for returning error code.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@@ -88,8 +74,8 @@ pub mod aarch64;
|
|||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
pub use aarch64::{
|
pub use aarch64::{
|
||||||
arch_memory_regions, configure_system, configure_vcpu, fdt::DeviceInfoForFdt,
|
arch_memory_regions, configure_system, configure_vcpu, fdt::DeviceInfoForFdt,
|
||||||
get_host_cpu_phys_bits, get_kernel_start, initramfs_load_addr, layout,
|
get_host_cpu_phys_bits, get_kernel_start, get_uefi_start, initramfs_load_addr, layout,
|
||||||
layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE, layout::IRQ_MAX, EntryPoint,
|
layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE, uefi, EntryPoint,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
@@ -98,8 +84,8 @@ pub mod x86_64;
|
|||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub use x86_64::{
|
pub use x86_64::{
|
||||||
arch_memory_regions, configure_system, configure_vcpu, get_host_cpu_phys_bits,
|
arch_memory_regions, configure_system, configure_vcpu, get_host_cpu_phys_bits,
|
||||||
initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, regs,
|
initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, regs, CpuidPatch,
|
||||||
BootProtocol, CpuidPatch, CpuidReg, EntryPoint,
|
CpuidReg, EntryPoint,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
|
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
|
||||||
|
|||||||
@@ -12,12 +12,6 @@ use std::mem;
|
|||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Error {
|
|
||||||
GetLapic(anyhow::Error),
|
|
||||||
SetLapic(anyhow::Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type Result<T> = result::Result<T, hypervisor::HypervisorCpuError>;
|
pub type Result<T> = result::Result<T, hypervisor::HypervisorCpuError>;
|
||||||
|
|
||||||
// Defines poached from apicdef.h kernel header.
|
// Defines poached from apicdef.h kernel header.
|
||||||
|
|||||||
@@ -9,40 +9,27 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
pub mod interrupts;
|
pub mod interrupts;
|
||||||
pub mod layout;
|
pub mod layout;
|
||||||
|
mod mpspec;
|
||||||
mod mptable;
|
mod mptable;
|
||||||
pub mod regs;
|
pub mod regs;
|
||||||
|
use crate::GuestMemoryMmap;
|
||||||
use crate::InitramfsConfig;
|
use crate::InitramfsConfig;
|
||||||
use crate::RegionType;
|
use crate::RegionType;
|
||||||
use hypervisor::{CpuId, CpuIdEntry, CPUID_FLAG_VALID_INDEX};
|
use hypervisor::{CpuId, CpuIdEntry, CPUID_FLAG_VALID_INDEX};
|
||||||
use linux_loader::loader::bootparam::{boot_params, setup_header};
|
use linux_loader::loader::bootparam::boot_params;
|
||||||
use linux_loader::loader::elf::start_info::{
|
use linux_loader::loader::elf::start_info::{
|
||||||
hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info,
|
hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info,
|
||||||
};
|
};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use vm_memory::{
|
use vm_memory::{
|
||||||
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic,
|
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic,
|
||||||
GuestMemoryMmap, GuestMemoryRegion, GuestUsize,
|
GuestMemoryRegion, GuestUsize,
|
||||||
};
|
};
|
||||||
mod smbios;
|
mod smbios;
|
||||||
use std::arch::x86_64;
|
use std::arch::x86_64;
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
pub mod tdx;
|
pub mod tdx;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub enum BootProtocol {
|
|
||||||
LinuxBoot,
|
|
||||||
PvhBoot,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::fmt::Display for BootProtocol {
|
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
BootProtocol::LinuxBoot => write!(f, "Linux 64-bit boot protocol"),
|
|
||||||
BootProtocol::PvhBoot => write!(f, "PVH boot protocol"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
/// Specifies the entry point address where the guest must start
|
/// Specifies the entry point address where the guest must start
|
||||||
/// executing code, as well as which of the supported boot protocols
|
/// executing code, as well as which of the supported boot protocols
|
||||||
@@ -50,10 +37,6 @@ impl ::std::fmt::Display for BootProtocol {
|
|||||||
pub struct EntryPoint {
|
pub struct EntryPoint {
|
||||||
/// Address in guest memory where the guest must start execution
|
/// Address in guest memory where the guest must start execution
|
||||||
pub entry_addr: GuestAddress,
|
pub entry_addr: GuestAddress,
|
||||||
/// Specifies which boot protocol to use
|
|
||||||
pub protocol: BootProtocol,
|
|
||||||
/// This field is used for bzImage to fill zero page
|
|
||||||
pub setup_header: Option<setup_header>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const E820_RAM: u32 = 1;
|
const E820_RAM: u32 = 1;
|
||||||
@@ -140,9 +123,6 @@ unsafe impl ByteValued for BootParamsWrapper {}
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Invalid e820 setup params.
|
|
||||||
E820Configuration,
|
|
||||||
|
|
||||||
/// Error writing MP table to memory.
|
/// Error writing MP table to memory.
|
||||||
MpTableSetup(mptable::Error),
|
MpTableSetup(mptable::Error),
|
||||||
|
|
||||||
@@ -351,17 +331,10 @@ pub fn configure_vcpu(
|
|||||||
regs::setup_msrs(fd).map_err(Error::MsrsConfiguration)?;
|
regs::setup_msrs(fd).map_err(Error::MsrsConfiguration)?;
|
||||||
if let Some(kernel_entry_point) = kernel_entry_point {
|
if let Some(kernel_entry_point) = kernel_entry_point {
|
||||||
// Safe to unwrap because this method is called after the VM is configured
|
// Safe to unwrap because this method is called after the VM is configured
|
||||||
regs::setup_regs(
|
regs::setup_regs(fd, kernel_entry_point.entry_addr.raw_value())
|
||||||
fd,
|
.map_err(Error::RegsConfiguration)?;
|
||||||
kernel_entry_point.entry_addr.raw_value(),
|
|
||||||
layout::BOOT_STACK_POINTER.raw_value(),
|
|
||||||
layout::ZERO_PAGE_START.raw_value(),
|
|
||||||
kernel_entry_point.protocol,
|
|
||||||
)
|
|
||||||
.map_err(Error::RegsConfiguration)?;
|
|
||||||
regs::setup_fpu(fd).map_err(Error::FpuConfiguration)?;
|
regs::setup_fpu(fd).map_err(Error::FpuConfiguration)?;
|
||||||
regs::setup_sregs(&vm_memory.memory(), fd, kernel_entry_point.protocol)
|
regs::setup_sregs(&vm_memory.memory(), fd).map_err(Error::SregsConfiguration)?;
|
||||||
.map_err(Error::SregsConfiguration)?;
|
|
||||||
}
|
}
|
||||||
interrupts::set_lint(fd).map_err(|e| Error::LocalIntConfiguration(e.into()))?;
|
interrupts::set_lint(fd).map_err(|e| Error::LocalIntConfiguration(e.into()))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -426,12 +399,9 @@ pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, Region
|
|||||||
pub fn configure_system(
|
pub fn configure_system(
|
||||||
guest_mem: &GuestMemoryMmap,
|
guest_mem: &GuestMemoryMmap,
|
||||||
cmdline_addr: GuestAddress,
|
cmdline_addr: GuestAddress,
|
||||||
cmdline_size: usize,
|
|
||||||
initramfs: &Option<InitramfsConfig>,
|
initramfs: &Option<InitramfsConfig>,
|
||||||
_num_cpus: u8,
|
_num_cpus: u8,
|
||||||
setup_hdr: Option<setup_header>,
|
|
||||||
rsdp_addr: Option<GuestAddress>,
|
rsdp_addr: Option<GuestAddress>,
|
||||||
boot_prot: BootProtocol,
|
|
||||||
sgx_epc_region: Option<SgxEpcRegion>,
|
sgx_epc_region: Option<SgxEpcRegion>,
|
||||||
) -> super::Result<()> {
|
) -> super::Result<()> {
|
||||||
let size = smbios::setup_smbios(guest_mem).map_err(Error::SmbiosSetup)?;
|
let size = smbios::setup_smbios(guest_mem).map_err(Error::SmbiosSetup)?;
|
||||||
@@ -448,31 +418,13 @@ pub fn configure_system(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match boot_prot {
|
configure_pvh(
|
||||||
BootProtocol::PvhBoot => {
|
guest_mem,
|
||||||
configure_pvh(
|
cmdline_addr,
|
||||||
guest_mem,
|
initramfs,
|
||||||
cmdline_addr,
|
rsdp_addr,
|
||||||
initramfs,
|
sgx_epc_region,
|
||||||
rsdp_addr,
|
)
|
||||||
sgx_epc_region,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
BootProtocol::LinuxBoot => {
|
|
||||||
error!("Using deprecated LinuxBoot protocol: Please configure your kernel with CONFIG_PVH=y and supply the `vmlinux` file to `--kernel`");
|
|
||||||
configure_64bit_boot(
|
|
||||||
guest_mem,
|
|
||||||
cmdline_addr,
|
|
||||||
cmdline_size,
|
|
||||||
initramfs,
|
|
||||||
setup_hdr,
|
|
||||||
rsdp_addr,
|
|
||||||
sgx_epc_region,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure_pvh(
|
fn configure_pvh(
|
||||||
@@ -615,121 +567,6 @@ fn add_memmap_entry(memmap: &mut Vec<hvm_memmap_table_entry>, addr: u64, size: u
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure_64bit_boot(
|
|
||||||
guest_mem: &GuestMemoryMmap,
|
|
||||||
cmdline_addr: GuestAddress,
|
|
||||||
cmdline_size: usize,
|
|
||||||
initramfs: &Option<InitramfsConfig>,
|
|
||||||
setup_hdr: Option<setup_header>,
|
|
||||||
rsdp_addr: Option<GuestAddress>,
|
|
||||||
sgx_epc_region: Option<SgxEpcRegion>,
|
|
||||||
) -> super::Result<()> {
|
|
||||||
const KERNEL_BOOT_FLAG_MAGIC: u16 = 0xaa55;
|
|
||||||
const KERNEL_HDR_MAGIC: u32 = 0x53726448;
|
|
||||||
const KERNEL_LOADER_OTHER: u8 = 0xff;
|
|
||||||
const KERNEL_MIN_ALIGNMENT_BYTES: u32 = 0x1000000; // Must be non-zero.
|
|
||||||
|
|
||||||
let mut params: BootParamsWrapper = BootParamsWrapper(boot_params::default());
|
|
||||||
|
|
||||||
if let Some(hdr) = setup_hdr {
|
|
||||||
// We should use the header if the loader provides one (e.g. from a bzImage).
|
|
||||||
params.0.hdr = hdr;
|
|
||||||
} else {
|
|
||||||
params.0.hdr.boot_flag = KERNEL_BOOT_FLAG_MAGIC;
|
|
||||||
params.0.hdr.header = KERNEL_HDR_MAGIC;
|
|
||||||
params.0.hdr.kernel_alignment = KERNEL_MIN_ALIGNMENT_BYTES;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Common bootparams settings
|
|
||||||
if params.0.hdr.type_of_loader == 0 {
|
|
||||||
params.0.hdr.type_of_loader = KERNEL_LOADER_OTHER;
|
|
||||||
}
|
|
||||||
params.0.hdr.cmd_line_ptr = cmdline_addr.raw_value() as u32;
|
|
||||||
params.0.hdr.cmdline_size = cmdline_size as u32;
|
|
||||||
|
|
||||||
if let Some(initramfs_config) = initramfs {
|
|
||||||
params.0.hdr.ramdisk_image = initramfs_config.address.raw_value() as u32;
|
|
||||||
params.0.hdr.ramdisk_size = initramfs_config.size as u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
add_e820_entry(&mut params.0, 0, layout::EBDA_START.raw_value(), E820_RAM)?;
|
|
||||||
|
|
||||||
let mem_end = guest_mem.last_addr();
|
|
||||||
if mem_end < layout::MEM_32BIT_RESERVED_START {
|
|
||||||
add_e820_entry(
|
|
||||||
&mut params.0,
|
|
||||||
layout::HIGH_RAM_START.raw_value(),
|
|
||||||
mem_end.unchecked_offset_from(layout::HIGH_RAM_START) + 1,
|
|
||||||
E820_RAM,
|
|
||||||
)?;
|
|
||||||
} else {
|
|
||||||
add_e820_entry(
|
|
||||||
&mut params.0,
|
|
||||||
layout::HIGH_RAM_START.raw_value(),
|
|
||||||
layout::MEM_32BIT_RESERVED_START.unchecked_offset_from(layout::HIGH_RAM_START),
|
|
||||||
E820_RAM,
|
|
||||||
)?;
|
|
||||||
if mem_end > layout::RAM_64BIT_START {
|
|
||||||
add_e820_entry(
|
|
||||||
&mut params.0,
|
|
||||||
layout::RAM_64BIT_START.raw_value(),
|
|
||||||
mem_end.unchecked_offset_from(layout::RAM_64BIT_START) + 1,
|
|
||||||
E820_RAM,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
add_e820_entry(
|
|
||||||
&mut params.0,
|
|
||||||
layout::PCI_MMCONFIG_START.0,
|
|
||||||
layout::PCI_MMCONFIG_SIZE,
|
|
||||||
E820_RESERVED,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if let Some(sgx_epc_region) = sgx_epc_region {
|
|
||||||
add_e820_entry(
|
|
||||||
&mut params.0,
|
|
||||||
sgx_epc_region.start().raw_value(),
|
|
||||||
sgx_epc_region.size() as u64,
|
|
||||||
E820_RESERVED,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(rsdp_addr) = rsdp_addr {
|
|
||||||
params.0.acpi_rsdp_addr = rsdp_addr.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let zero_page_addr = layout::ZERO_PAGE_START;
|
|
||||||
guest_mem
|
|
||||||
.checked_offset(zero_page_addr, mem::size_of::<boot_params>())
|
|
||||||
.ok_or(super::Error::ZeroPagePastRamEnd)?;
|
|
||||||
guest_mem
|
|
||||||
.write_obj(params, zero_page_addr)
|
|
||||||
.map_err(super::Error::ZeroPageSetup)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add an e820 region to the e820 map.
|
|
||||||
/// Returns Ok(()) if successful, or an error if there is no space left in the map.
|
|
||||||
fn add_e820_entry(
|
|
||||||
params: &mut boot_params,
|
|
||||||
addr: u64,
|
|
||||||
size: u64,
|
|
||||||
mem_type: u32,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if params.e820_entries >= params.e820_table.len() as u8 {
|
|
||||||
return Err(Error::E820Configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
params.e820_table[params.e820_entries as usize].addr = addr;
|
|
||||||
params.e820_table[params.e820_entries as usize].size = size;
|
|
||||||
params.e820_table[params.e820_entries as usize].type_ = mem_type;
|
|
||||||
params.e820_entries += 1;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the memory address where the initramfs could be loaded.
|
/// Returns the memory address where the initramfs could be loaded.
|
||||||
pub fn initramfs_load_addr(
|
pub fn initramfs_load_addr(
|
||||||
guest_mem: &GuestMemoryMmap,
|
guest_mem: &GuestMemoryMmap,
|
||||||
@@ -888,7 +725,6 @@ pub fn update_cpuid_sgx(cpuid: &mut CpuId, epc_sections: Vec<SgxEpcSection>) ->
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use linux_loader::loader::bootparam::boot_e820_entry;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn regions_lt_4gb() {
|
fn regions_lt_4gb() {
|
||||||
@@ -913,12 +749,9 @@ mod tests {
|
|||||||
let config_err = configure_system(
|
let config_err = configure_system(
|
||||||
&gm,
|
&gm,
|
||||||
GuestAddress(0),
|
GuestAddress(0),
|
||||||
0,
|
|
||||||
&None,
|
&None,
|
||||||
1,
|
1,
|
||||||
None,
|
|
||||||
Some(layout::RSDP_POINTER),
|
Some(layout::RSDP_POINTER),
|
||||||
BootProtocol::LinuxBoot,
|
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
assert!(config_err.is_err());
|
assert!(config_err.is_err());
|
||||||
@@ -932,31 +765,8 @@ mod tests {
|
|||||||
.map(|r| (r.0, r.1))
|
.map(|r| (r.0, r.1))
|
||||||
.collect();
|
.collect();
|
||||||
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
||||||
configure_system(
|
|
||||||
&gm,
|
|
||||||
GuestAddress(0),
|
|
||||||
0,
|
|
||||||
&None,
|
|
||||||
no_vcpus,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
BootProtocol::LinuxBoot,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
configure_system(
|
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
|
||||||
&gm,
|
|
||||||
GuestAddress(0),
|
|
||||||
0,
|
|
||||||
&None,
|
|
||||||
no_vcpus,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
BootProtocol::PvhBoot,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Now assigning some memory that is equal to the start of the 32bit memory hole.
|
// Now assigning some memory that is equal to the start of the 32bit memory hole.
|
||||||
let mem_size = 3328 << 20;
|
let mem_size = 3328 << 20;
|
||||||
@@ -967,31 +777,9 @@ mod tests {
|
|||||||
.map(|r| (r.0, r.1))
|
.map(|r| (r.0, r.1))
|
||||||
.collect();
|
.collect();
|
||||||
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
||||||
configure_system(
|
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
|
||||||
&gm,
|
|
||||||
GuestAddress(0),
|
|
||||||
0,
|
|
||||||
&None,
|
|
||||||
no_vcpus,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
BootProtocol::LinuxBoot,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
configure_system(
|
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
|
||||||
&gm,
|
|
||||||
GuestAddress(0),
|
|
||||||
0,
|
|
||||||
&None,
|
|
||||||
no_vcpus,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
BootProtocol::PvhBoot,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Now assigning some memory that falls after the 32bit memory hole.
|
// Now assigning some memory that falls after the 32bit memory hole.
|
||||||
let mem_size = 3330 << 20;
|
let mem_size = 3330 << 20;
|
||||||
@@ -1002,71 +790,9 @@ mod tests {
|
|||||||
.map(|r| (r.0, r.1))
|
.map(|r| (r.0, r.1))
|
||||||
.collect();
|
.collect();
|
||||||
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
||||||
configure_system(
|
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
|
||||||
&gm,
|
|
||||||
GuestAddress(0),
|
|
||||||
0,
|
|
||||||
&None,
|
|
||||||
no_vcpus,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
BootProtocol::LinuxBoot,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
configure_system(
|
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
|
||||||
&gm,
|
|
||||||
GuestAddress(0),
|
|
||||||
0,
|
|
||||||
&None,
|
|
||||||
no_vcpus,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
BootProtocol::PvhBoot,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_add_e820_entry() {
|
|
||||||
let e820_table = [(boot_e820_entry {
|
|
||||||
addr: 0x1,
|
|
||||||
size: 4,
|
|
||||||
type_: 1,
|
|
||||||
}); 128];
|
|
||||||
|
|
||||||
let expected_params = boot_params {
|
|
||||||
e820_table,
|
|
||||||
e820_entries: 1,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut params: boot_params = Default::default();
|
|
||||||
add_e820_entry(
|
|
||||||
&mut params,
|
|
||||||
e820_table[0].addr,
|
|
||||||
e820_table[0].size,
|
|
||||||
e820_table[0].type_,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
format!("{:?}", params.e820_table[0]),
|
|
||||||
format!("{:?}", expected_params.e820_table[0])
|
|
||||||
);
|
|
||||||
assert_eq!(params.e820_entries, expected_params.e820_entries);
|
|
||||||
|
|
||||||
// Exercise the scenario where the field storing the length of the e820 entry table is
|
|
||||||
// is bigger than the allocated memory.
|
|
||||||
params.e820_entries = params.e820_table.len() as u8 + 1;
|
|
||||||
assert!(add_e820_entry(
|
|
||||||
&mut params,
|
|
||||||
e820_table[0].addr,
|
|
||||||
e820_table[0].size,
|
|
||||||
e820_table[0].type_
|
|
||||||
)
|
|
||||||
.is_err());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
112
arch/src/x86_64/mpspec.rs
Normal file
112
arch/src/x86_64/mpspec.rs
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE-BSD-3-Clause file.
|
||||||
|
|
||||||
|
pub const MP_PROCESSOR: ::std::os::raw::c_uint = 0;
|
||||||
|
pub const MP_BUS: ::std::os::raw::c_uint = 1;
|
||||||
|
pub const MP_IOAPIC: ::std::os::raw::c_uint = 2;
|
||||||
|
pub const MP_INTSRC: ::std::os::raw::c_uint = 3;
|
||||||
|
pub const MP_LINTSRC: ::std::os::raw::c_uint = 4;
|
||||||
|
pub const CPU_ENABLED: ::std::os::raw::c_uint = 1;
|
||||||
|
pub const CPU_BOOTPROCESSOR: ::std::os::raw::c_uint = 2;
|
||||||
|
pub const MPC_APIC_USABLE: ::std::os::raw::c_uint = 1;
|
||||||
|
pub const MP_IRQDIR_DEFAULT: ::std::os::raw::c_uint = 0;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct mpf_intel {
|
||||||
|
pub signature: [::std::os::raw::c_char; 4usize],
|
||||||
|
pub physptr: ::std::os::raw::c_uint,
|
||||||
|
pub length: ::std::os::raw::c_uchar,
|
||||||
|
pub specification: ::std::os::raw::c_uchar,
|
||||||
|
pub checksum: ::std::os::raw::c_uchar,
|
||||||
|
pub feature1: ::std::os::raw::c_uchar,
|
||||||
|
pub feature2: ::std::os::raw::c_uchar,
|
||||||
|
pub feature3: ::std::os::raw::c_uchar,
|
||||||
|
pub feature4: ::std::os::raw::c_uchar,
|
||||||
|
pub feature5: ::std::os::raw::c_uchar,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct mpc_table {
|
||||||
|
pub signature: [::std::os::raw::c_char; 4usize],
|
||||||
|
pub length: ::std::os::raw::c_ushort,
|
||||||
|
pub spec: ::std::os::raw::c_char,
|
||||||
|
pub checksum: ::std::os::raw::c_char,
|
||||||
|
pub oem: [::std::os::raw::c_char; 8usize],
|
||||||
|
pub productid: [::std::os::raw::c_char; 12usize],
|
||||||
|
pub oemptr: ::std::os::raw::c_uint,
|
||||||
|
pub oemsize: ::std::os::raw::c_ushort,
|
||||||
|
pub oemcount: ::std::os::raw::c_ushort,
|
||||||
|
pub lapic: ::std::os::raw::c_uint,
|
||||||
|
pub reserved: ::std::os::raw::c_uint,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct mpc_cpu {
|
||||||
|
pub type_: ::std::os::raw::c_uchar,
|
||||||
|
pub apicid: ::std::os::raw::c_uchar,
|
||||||
|
pub apicver: ::std::os::raw::c_uchar,
|
||||||
|
pub cpuflag: ::std::os::raw::c_uchar,
|
||||||
|
pub cpufeature: ::std::os::raw::c_uint,
|
||||||
|
pub featureflag: ::std::os::raw::c_uint,
|
||||||
|
pub reserved: [::std::os::raw::c_uint; 2usize],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct mpc_bus {
|
||||||
|
pub type_: ::std::os::raw::c_uchar,
|
||||||
|
pub busid: ::std::os::raw::c_uchar,
|
||||||
|
pub bustype: [::std::os::raw::c_uchar; 6usize],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct mpc_ioapic {
|
||||||
|
pub type_: ::std::os::raw::c_uchar,
|
||||||
|
pub apicid: ::std::os::raw::c_uchar,
|
||||||
|
pub apicver: ::std::os::raw::c_uchar,
|
||||||
|
pub flags: ::std::os::raw::c_uchar,
|
||||||
|
pub apicaddr: ::std::os::raw::c_uint,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct mpc_intsrc {
|
||||||
|
pub type_: ::std::os::raw::c_uchar,
|
||||||
|
pub irqtype: ::std::os::raw::c_uchar,
|
||||||
|
pub irqflag: ::std::os::raw::c_ushort,
|
||||||
|
pub srcbus: ::std::os::raw::c_uchar,
|
||||||
|
pub srcbusirq: ::std::os::raw::c_uchar,
|
||||||
|
pub dstapic: ::std::os::raw::c_uchar,
|
||||||
|
pub dstirq: ::std::os::raw::c_uchar,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const MP_IRQ_SOURCE_TYPES_MP_INT: ::std::os::raw::c_uint = 0;
|
||||||
|
pub const MP_IRQ_SOURCE_TYPES_MP_NMI: ::std::os::raw::c_uint = 1;
|
||||||
|
pub const MP_IRQ_SOURCE_TYPES_MP_EXT_INT: ::std::os::raw::c_uint = 3;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct mpc_lintsrc {
|
||||||
|
pub type_: ::std::os::raw::c_uchar,
|
||||||
|
pub irqtype: ::std::os::raw::c_uchar,
|
||||||
|
pub irqflag: ::std::os::raw::c_ushort,
|
||||||
|
pub srcbusid: ::std::os::raw::c_uchar,
|
||||||
|
pub srcbusirq: ::std::os::raw::c_uchar,
|
||||||
|
pub destapic: ::std::os::raw::c_uchar,
|
||||||
|
pub destapiclint: ::std::os::raw::c_uchar,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct mpc_oemtable {
|
||||||
|
pub signature: [::std::os::raw::c_char; 4usize],
|
||||||
|
pub length: ::std::os::raw::c_ushort,
|
||||||
|
pub rev: ::std::os::raw::c_char,
|
||||||
|
pub checksum: ::std::os::raw::c_char,
|
||||||
|
pub mpc: [::std::os::raw::c_char; 8usize],
|
||||||
|
}
|
||||||
@@ -5,18 +5,15 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE-BSD-3-Clause file.
|
// found in the LICENSE-BSD-3-Clause file.
|
||||||
|
|
||||||
|
use crate::layout::{APIC_START, HIGH_RAM_START, IOAPIC_START};
|
||||||
|
use crate::x86_64::mpspec;
|
||||||
|
use crate::GuestMemoryMmap;
|
||||||
|
use libc::c_char;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
use vm_memory::{Address, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryError};
|
||||||
use libc::c_char;
|
|
||||||
|
|
||||||
use arch_gen::x86::mpspec;
|
|
||||||
use layout::{APIC_START, HIGH_RAM_START, IOAPIC_START};
|
|
||||||
use vm_memory::{
|
|
||||||
Address, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryError, GuestMemoryMmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is a workaround to the Rust enforcement specifying that any implementation of a foreign
|
// This is a workaround to the Rust enforcement specifying that any implementation of a foreign
|
||||||
// trait (in this case `ByteValued`) where:
|
// trait (in this case `ByteValued`) where:
|
||||||
@@ -222,7 +219,7 @@ pub fn setup_mptable(offset: GuestAddress, mem: &GuestMemoryMmap, num_cpus: u8)
|
|||||||
let size = mem::size_of::<MpcIntsrcWrapper>();
|
let size = mem::size_of::<MpcIntsrcWrapper>();
|
||||||
let mut mpc_intsrc = MpcIntsrcWrapper(mpspec::mpc_intsrc::default());
|
let mut mpc_intsrc = MpcIntsrcWrapper(mpspec::mpc_intsrc::default());
|
||||||
mpc_intsrc.0.type_ = mpspec::MP_INTSRC as u8;
|
mpc_intsrc.0.type_ = mpspec::MP_INTSRC as u8;
|
||||||
mpc_intsrc.0.irqtype = mpspec::mp_irq_source_types_mp_INT as u8;
|
mpc_intsrc.0.irqtype = mpspec::MP_IRQ_SOURCE_TYPES_MP_INT as u8;
|
||||||
mpc_intsrc.0.irqflag = mpspec::MP_IRQDIR_DEFAULT as u16;
|
mpc_intsrc.0.irqflag = mpspec::MP_IRQDIR_DEFAULT as u16;
|
||||||
mpc_intsrc.0.srcbus = 0;
|
mpc_intsrc.0.srcbus = 0;
|
||||||
mpc_intsrc.0.srcbusirq = i;
|
mpc_intsrc.0.srcbusirq = i;
|
||||||
@@ -237,7 +234,7 @@ pub fn setup_mptable(offset: GuestAddress, mem: &GuestMemoryMmap, num_cpus: u8)
|
|||||||
let size = mem::size_of::<MpcLintsrcWrapper>();
|
let size = mem::size_of::<MpcLintsrcWrapper>();
|
||||||
let mut mpc_lintsrc = MpcLintsrcWrapper(mpspec::mpc_lintsrc::default());
|
let mut mpc_lintsrc = MpcLintsrcWrapper(mpspec::mpc_lintsrc::default());
|
||||||
mpc_lintsrc.0.type_ = mpspec::MP_LINTSRC as u8;
|
mpc_lintsrc.0.type_ = mpspec::MP_LINTSRC as u8;
|
||||||
mpc_lintsrc.0.irqtype = mpspec::mp_irq_source_types_mp_ExtINT as u8;
|
mpc_lintsrc.0.irqtype = mpspec::MP_IRQ_SOURCE_TYPES_MP_EXT_INT as u8;
|
||||||
mpc_lintsrc.0.irqflag = mpspec::MP_IRQDIR_DEFAULT as u16;
|
mpc_lintsrc.0.irqflag = mpspec::MP_IRQDIR_DEFAULT as u16;
|
||||||
mpc_lintsrc.0.srcbusid = 0;
|
mpc_lintsrc.0.srcbusid = 0;
|
||||||
mpc_lintsrc.0.srcbusirq = 0;
|
mpc_lintsrc.0.srcbusirq = 0;
|
||||||
@@ -252,7 +249,7 @@ pub fn setup_mptable(offset: GuestAddress, mem: &GuestMemoryMmap, num_cpus: u8)
|
|||||||
let size = mem::size_of::<MpcLintsrcWrapper>();
|
let size = mem::size_of::<MpcLintsrcWrapper>();
|
||||||
let mut mpc_lintsrc = MpcLintsrcWrapper(mpspec::mpc_lintsrc::default());
|
let mut mpc_lintsrc = MpcLintsrcWrapper(mpspec::mpc_lintsrc::default());
|
||||||
mpc_lintsrc.0.type_ = mpspec::MP_LINTSRC as u8;
|
mpc_lintsrc.0.type_ = mpspec::MP_LINTSRC as u8;
|
||||||
mpc_lintsrc.0.irqtype = mpspec::mp_irq_source_types_mp_NMI as u8;
|
mpc_lintsrc.0.irqtype = mpspec::MP_IRQ_SOURCE_TYPES_MP_NMI as u8;
|
||||||
mpc_lintsrc.0.irqflag = mpspec::MP_IRQDIR_DEFAULT as u16;
|
mpc_lintsrc.0.irqflag = mpspec::MP_IRQDIR_DEFAULT as u16;
|
||||||
mpc_lintsrc.0.srcbusid = 0;
|
mpc_lintsrc.0.srcbusid = 0;
|
||||||
mpc_lintsrc.0.srcbusirq = 0;
|
mpc_lintsrc.0.srcbusirq = 0;
|
||||||
@@ -287,7 +284,7 @@ pub fn setup_mptable(offset: GuestAddress, mem: &GuestMemoryMmap, num_cpus: u8)
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use layout::MPTABLE_START;
|
use crate::layout::MPTABLE_START;
|
||||||
use vm_memory::{GuestAddress, GuestUsize};
|
use vm_memory::{GuestAddress, GuestUsize};
|
||||||
|
|
||||||
fn table_entry_size(type_: u8) -> usize {
|
fn table_entry_size(type_: u8) -> usize {
|
||||||
|
|||||||
@@ -6,17 +6,14 @@
|
|||||||
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
|
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE-BSD-3-Clause file.
|
// found in the LICENSE-BSD-3-Clause file.
|
||||||
use std::sync::Arc;
|
use crate::layout::{BOOT_GDT_START, BOOT_IDT_START, PVH_INFO_START};
|
||||||
use std::{mem, result};
|
use crate::GuestMemoryMmap;
|
||||||
|
|
||||||
use super::BootProtocol;
|
|
||||||
use hypervisor::arch::x86::gdt::{gdt_entry, segment_from_gdt};
|
use hypervisor::arch::x86::gdt::{gdt_entry, segment_from_gdt};
|
||||||
use hypervisor::arch::x86::regs::*;
|
use hypervisor::arch::x86::regs::*;
|
||||||
use hypervisor::x86_64::{FpuState, SpecialRegisters, StandardRegisters};
|
use hypervisor::x86_64::{FpuState, SpecialRegisters, StandardRegisters};
|
||||||
use layout::{
|
use std::sync::Arc;
|
||||||
BOOT_GDT_START, BOOT_IDT_START, PDE_START, PDPTE_START, PML4_START, PML5_START, PVH_INFO_START,
|
use std::{mem, result};
|
||||||
};
|
use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError};
|
||||||
use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError, GuestMemoryMmap};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@@ -81,32 +78,12 @@ pub fn setup_msrs(vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<()> {
|
|||||||
///
|
///
|
||||||
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
|
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
|
||||||
/// * `boot_ip` - Starting instruction pointer.
|
/// * `boot_ip` - Starting instruction pointer.
|
||||||
/// * `boot_sp` - Starting stack pointer.
|
pub fn setup_regs(vcpu: &Arc<dyn hypervisor::Vcpu>, boot_ip: u64) -> Result<()> {
|
||||||
/// * `boot_si` - Must point to zero page address per Linux ABI.
|
let regs = StandardRegisters {
|
||||||
pub fn setup_regs(
|
rflags: 0x0000000000000002u64,
|
||||||
vcpu: &Arc<dyn hypervisor::Vcpu>,
|
rbx: PVH_INFO_START.raw_value(),
|
||||||
boot_ip: u64,
|
rip: boot_ip,
|
||||||
boot_sp: u64,
|
..Default::default()
|
||||||
boot_si: u64,
|
|
||||||
boot_prot: BootProtocol,
|
|
||||||
) -> Result<()> {
|
|
||||||
let regs: StandardRegisters = match boot_prot {
|
|
||||||
// Configure regs as required by PVH boot protocol.
|
|
||||||
BootProtocol::PvhBoot => StandardRegisters {
|
|
||||||
rflags: 0x0000000000000002u64,
|
|
||||||
rbx: PVH_INFO_START.raw_value(),
|
|
||||||
rip: boot_ip,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
// Configure regs as required by Linux 64-bit boot protocol.
|
|
||||||
BootProtocol::LinuxBoot => StandardRegisters {
|
|
||||||
rflags: 0x0000000000000002u64,
|
|
||||||
rip: boot_ip,
|
|
||||||
rsp: boot_sp,
|
|
||||||
rbp: boot_sp,
|
|
||||||
rsi: boot_si,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
vcpu.set_regs(®s).map_err(Error::SetBaseRegisters)
|
vcpu.set_regs(®s).map_err(Error::SetBaseRegisters)
|
||||||
}
|
}
|
||||||
@@ -117,19 +94,9 @@ pub fn setup_regs(
|
|||||||
///
|
///
|
||||||
/// * `mem` - The memory that will be passed to the guest.
|
/// * `mem` - The memory that will be passed to the guest.
|
||||||
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
|
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
|
||||||
pub fn setup_sregs(
|
pub fn setup_sregs(mem: &GuestMemoryMmap, vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<()> {
|
||||||
mem: &GuestMemoryMmap,
|
|
||||||
vcpu: &Arc<dyn hypervisor::Vcpu>,
|
|
||||||
boot_prot: BootProtocol,
|
|
||||||
) -> Result<()> {
|
|
||||||
let mut sregs: SpecialRegisters = vcpu.get_sregs().map_err(Error::GetStatusRegisters)?;
|
let mut sregs: SpecialRegisters = vcpu.get_sregs().map_err(Error::GetStatusRegisters)?;
|
||||||
|
configure_segments_and_sregs(mem, &mut sregs)?;
|
||||||
configure_segments_and_sregs(mem, &mut sregs, boot_prot)?;
|
|
||||||
|
|
||||||
if let BootProtocol::LinuxBoot = boot_prot {
|
|
||||||
setup_page_tables(mem, &mut sregs)?; // TODO(dgreid) - Can this be done once per system instead?
|
|
||||||
}
|
|
||||||
|
|
||||||
vcpu.set_sregs(&sregs).map_err(Error::SetStatusRegisters)
|
vcpu.set_sregs(&sregs).map_err(Error::SetStatusRegisters)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,27 +123,15 @@ fn write_idt_value(val: u64, guest_mem: &GuestMemoryMmap) -> Result<()> {
|
|||||||
pub fn configure_segments_and_sregs(
|
pub fn configure_segments_and_sregs(
|
||||||
mem: &GuestMemoryMmap,
|
mem: &GuestMemoryMmap,
|
||||||
sregs: &mut SpecialRegisters,
|
sregs: &mut SpecialRegisters,
|
||||||
boot_prot: BootProtocol,
|
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let gdt_table: [u64; BOOT_GDT_MAX as usize] = match boot_prot {
|
let gdt_table: [u64; BOOT_GDT_MAX as usize] = {
|
||||||
BootProtocol::PvhBoot => {
|
// Configure GDT entries as specified by PVH boot protocol
|
||||||
// Configure GDT entries as specified by PVH boot protocol
|
[
|
||||||
[
|
gdt_entry(0, 0, 0), // NULL
|
||||||
gdt_entry(0, 0, 0), // NULL
|
gdt_entry(0xc09b, 0, 0xffffffff), // CODE
|
||||||
gdt_entry(0xc09b, 0, 0xffffffff), // CODE
|
gdt_entry(0xc093, 0, 0xffffffff), // DATA
|
||||||
gdt_entry(0xc093, 0, 0xffffffff), // DATA
|
gdt_entry(0x008b, 0, 0x67), // TSS
|
||||||
gdt_entry(0x008b, 0, 0x67), // TSS
|
]
|
||||||
]
|
|
||||||
}
|
|
||||||
BootProtocol::LinuxBoot => {
|
|
||||||
// Configure GDT entries as specified by Linux 64bit boot protocol
|
|
||||||
[
|
|
||||||
gdt_entry(0, 0, 0), // NULL
|
|
||||||
gdt_entry(0xa09b, 0, 0xfffff), // CODE
|
|
||||||
gdt_entry(0xc093, 0, 0xfffff), // DATA
|
|
||||||
gdt_entry(0x808b, 0, 0xfffff), // TSS
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let code_seg = segment_from_gdt(gdt_table[1], 1);
|
let code_seg = segment_from_gdt(gdt_table[1], 1);
|
||||||
@@ -200,61 +155,17 @@ pub fn configure_segments_and_sregs(
|
|||||||
sregs.ss = data_seg;
|
sregs.ss = data_seg;
|
||||||
sregs.tr = tss_seg;
|
sregs.tr = tss_seg;
|
||||||
|
|
||||||
match boot_prot {
|
sregs.cr0 = CR0_PE;
|
||||||
BootProtocol::PvhBoot => {
|
sregs.cr4 = 0;
|
||||||
sregs.cr0 = CR0_PE;
|
|
||||||
sregs.cr4 = 0;
|
|
||||||
}
|
|
||||||
BootProtocol::LinuxBoot => {
|
|
||||||
/* 64-bit protected mode */
|
|
||||||
sregs.cr0 |= CR0_PE;
|
|
||||||
sregs.efer |= EFER_LME | EFER_LMA;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setup_page_tables(mem: &GuestMemoryMmap, sregs: &mut SpecialRegisters) -> Result<()> {
|
|
||||||
// Puts PML5 or PML4 right after zero page but aligned to 4k.
|
|
||||||
if unsafe { std::arch::x86_64::__cpuid(7).ecx } & (1 << 16) != 0 {
|
|
||||||
// Entry covering VA [0..256TB)
|
|
||||||
mem.write_obj(PML4_START.raw_value() | 0x03, PML5_START)
|
|
||||||
.map_err(Error::WritePml5Address)?;
|
|
||||||
|
|
||||||
sregs.cr3 = PML5_START.raw_value();
|
|
||||||
sregs.cr4 |= CR4_LA57;
|
|
||||||
} else {
|
|
||||||
sregs.cr3 = PML4_START.raw_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Entry covering VA [0..512GB)
|
|
||||||
mem.write_obj(PDPTE_START.raw_value() | 0x03, PML4_START)
|
|
||||||
.map_err(Error::WritePml4Address)?;
|
|
||||||
|
|
||||||
// Entry covering VA [0..1GB)
|
|
||||||
mem.write_obj(PDE_START.raw_value() | 0x03, PDPTE_START)
|
|
||||||
.map_err(Error::WritePdpteAddress)?;
|
|
||||||
|
|
||||||
// 512 2MB entries together covering VA [0..1GB). Note we are assuming
|
|
||||||
// CPU supports 2MB pages (/proc/cpuinfo has 'pse'). All modern CPUs do.
|
|
||||||
for i in 0..512 {
|
|
||||||
mem.write_obj((i << 21) + 0x83u64, PDE_START.unchecked_add(i * 8))
|
|
||||||
.map_err(Error::WritePdeAddress)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
sregs.cr4 |= CR4_PAE;
|
|
||||||
sregs.cr0 |= CR0_PG;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
extern crate vm_memory;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use vm_memory::{GuestAddress, GuestMemoryMmap};
|
use crate::GuestMemoryMmap;
|
||||||
|
use vm_memory::GuestAddress;
|
||||||
|
|
||||||
fn create_guest_mem() -> GuestMemoryMmap {
|
fn create_guest_mem() -> GuestMemoryMmap {
|
||||||
GuestMemoryMmap::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap()
|
GuestMemoryMmap::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap()
|
||||||
@@ -268,36 +179,7 @@ mod tests {
|
|||||||
fn segments_and_sregs() {
|
fn segments_and_sregs() {
|
||||||
let mut sregs: SpecialRegisters = Default::default();
|
let mut sregs: SpecialRegisters = Default::default();
|
||||||
let gm = create_guest_mem();
|
let gm = create_guest_mem();
|
||||||
configure_segments_and_sregs(&gm, &mut sregs, BootProtocol::LinuxBoot).unwrap();
|
configure_segments_and_sregs(&gm, &mut sregs).unwrap();
|
||||||
|
|
||||||
assert_eq!(0x0, read_u64(&gm, BOOT_GDT_START));
|
|
||||||
assert_eq!(
|
|
||||||
0xaf9b000000ffff,
|
|
||||||
read_u64(&gm, BOOT_GDT_START.unchecked_add(8))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
0xcf93000000ffff,
|
|
||||||
read_u64(&gm, BOOT_GDT_START.unchecked_add(16))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
0x8f8b000000ffff,
|
|
||||||
read_u64(&gm, BOOT_GDT_START.unchecked_add(24))
|
|
||||||
);
|
|
||||||
assert_eq!(0x0, read_u64(&gm, BOOT_IDT_START));
|
|
||||||
|
|
||||||
assert_eq!(0, sregs.cs.base);
|
|
||||||
assert_eq!(0xffffffff, sregs.ds.limit);
|
|
||||||
assert_eq!(0x10, sregs.es.selector);
|
|
||||||
assert_eq!(1, sregs.fs.present);
|
|
||||||
assert_eq!(1, sregs.gs.g);
|
|
||||||
assert_eq!(0, sregs.ss.avl);
|
|
||||||
assert_eq!(0, sregs.tr.base);
|
|
||||||
assert_eq!(0xffffffff, sregs.tr.limit);
|
|
||||||
assert_eq!(0, sregs.tr.avl);
|
|
||||||
assert_eq!(CR0_PE, sregs.cr0);
|
|
||||||
assert_eq!(EFER_LME | EFER_LMA, sregs.efer);
|
|
||||||
|
|
||||||
configure_segments_and_sregs(&gm, &mut sregs, BootProtocol::PvhBoot).unwrap();
|
|
||||||
assert_eq!(0x0, read_u64(&gm, BOOT_GDT_START));
|
assert_eq!(0x0, read_u64(&gm, BOOT_GDT_START));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
0xcf9b000000ffff,
|
0xcf9b000000ffff,
|
||||||
@@ -327,31 +209,4 @@ mod tests {
|
|||||||
assert_eq!(CR0_PE, sregs.cr0);
|
assert_eq!(CR0_PE, sregs.cr0);
|
||||||
assert_eq!(0, sregs.cr4);
|
assert_eq!(0, sregs.cr4);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn page_tables() {
|
|
||||||
let mut sregs: SpecialRegisters = Default::default();
|
|
||||||
let gm = create_guest_mem();
|
|
||||||
setup_page_tables(&gm, &mut sregs).unwrap();
|
|
||||||
|
|
||||||
if unsafe { std::arch::x86_64::__cpuid(7).ecx } & (1 << 16) != 0 {
|
|
||||||
assert_eq!(0xa003, read_u64(&gm, PML5_START));
|
|
||||||
}
|
|
||||||
assert_eq!(0xb003, read_u64(&gm, PML4_START));
|
|
||||||
assert_eq!(0xc003, read_u64(&gm, PDPTE_START));
|
|
||||||
for i in 0..512 {
|
|
||||||
assert_eq!(
|
|
||||||
(i << 21) + 0x83u64,
|
|
||||||
read_u64(&gm, PDE_START.unchecked_add(i * 8))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if unsafe { std::arch::x86_64::__cpuid(7).ecx } & (1 << 16) != 0 {
|
|
||||||
assert_eq!(PML5_START.raw_value(), sregs.cr3);
|
|
||||||
} else {
|
|
||||||
assert_eq!(PML4_START.raw_value(), sregs.cr3);
|
|
||||||
}
|
|
||||||
assert_eq!(CR4_PAE, sregs.cr4);
|
|
||||||
assert_eq!(CR0_PG, sregs.cr0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,14 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||||
|
|
||||||
use layout::SMBIOS_START;
|
use crate::layout::SMBIOS_START;
|
||||||
|
use crate::GuestMemoryMmap;
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use vm_memory::ByteValued;
|
use vm_memory::ByteValued;
|
||||||
use vm_memory::{Address, Bytes, GuestAddress, GuestMemoryMmap};
|
use vm_memory::{Address, Bytes, GuestAddress};
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
// Copyright © 2021 Intel Corporation
|
// Copyright © 2021 Intel Corporation
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
use crate::GuestMemoryMmap;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use vm_memory::{ByteValued, Bytes, GuestAddress, GuestMemoryError, GuestMemoryMmap};
|
use vm_memory::{ByteValued, Bytes, GuestAddress, GuestMemoryError};
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum TdvfError {
|
pub enum TdvfError {
|
||||||
|
|||||||
6
arch_gen/Cargo.lock
generated
6
arch_gen/Cargo.lock
generated
@@ -1,6 +0,0 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
|
||||||
# It is not intended for manual editing.
|
|
||||||
[[package]]
|
|
||||||
name = "arch_gen"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "arch_gen"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Amazon firecracker team <firecracker-devel@amazon.com>"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
|
||||||
pub mod x86;
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
//
|
|
||||||
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE-BSD-3-Clause file.
|
|
||||||
|
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
#[allow(clippy::unreadable_literal, clippy::redundant_static_lifetimes)]
|
|
||||||
pub mod mpspec;
|
|
||||||
@@ -1,832 +0,0 @@
|
|||||||
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE-BSD-3-Clause file.
|
|
||||||
|
|
||||||
/* automatically generated by rust-bindgen */
|
|
||||||
|
|
||||||
pub const MPC_SIGNATURE: &'static [u8; 5usize] = b"PCMP\x00";
|
|
||||||
pub const MP_PROCESSOR: ::std::os::raw::c_uint = 0;
|
|
||||||
pub const MP_BUS: ::std::os::raw::c_uint = 1;
|
|
||||||
pub const MP_IOAPIC: ::std::os::raw::c_uint = 2;
|
|
||||||
pub const MP_INTSRC: ::std::os::raw::c_uint = 3;
|
|
||||||
pub const MP_LINTSRC: ::std::os::raw::c_uint = 4;
|
|
||||||
pub const MP_TRANSLATION: ::std::os::raw::c_uint = 192;
|
|
||||||
pub const CPU_ENABLED: ::std::os::raw::c_uint = 1;
|
|
||||||
pub const CPU_BOOTPROCESSOR: ::std::os::raw::c_uint = 2;
|
|
||||||
pub const CPU_STEPPING_MASK: ::std::os::raw::c_uint = 15;
|
|
||||||
pub const CPU_MODEL_MASK: ::std::os::raw::c_uint = 240;
|
|
||||||
pub const CPU_FAMILY_MASK: ::std::os::raw::c_uint = 3840;
|
|
||||||
pub const BUSTYPE_EISA: &'static [u8; 5usize] = b"EISA\x00";
|
|
||||||
pub const BUSTYPE_ISA: &'static [u8; 4usize] = b"ISA\x00";
|
|
||||||
pub const BUSTYPE_INTERN: &'static [u8; 7usize] = b"INTERN\x00";
|
|
||||||
pub const BUSTYPE_MCA: &'static [u8; 4usize] = b"MCA\x00";
|
|
||||||
pub const BUSTYPE_VL: &'static [u8; 3usize] = b"VL\x00";
|
|
||||||
pub const BUSTYPE_PCI: &'static [u8; 4usize] = b"PCI\x00";
|
|
||||||
pub const BUSTYPE_PCMCIA: &'static [u8; 7usize] = b"PCMCIA\x00";
|
|
||||||
pub const BUSTYPE_CBUS: &'static [u8; 5usize] = b"CBUS\x00";
|
|
||||||
pub const BUSTYPE_CBUSII: &'static [u8; 7usize] = b"CBUSII\x00";
|
|
||||||
pub const BUSTYPE_FUTURE: &'static [u8; 7usize] = b"FUTURE\x00";
|
|
||||||
pub const BUSTYPE_MBI: &'static [u8; 4usize] = b"MBI\x00";
|
|
||||||
pub const BUSTYPE_MBII: &'static [u8; 5usize] = b"MBII\x00";
|
|
||||||
pub const BUSTYPE_MPI: &'static [u8; 4usize] = b"MPI\x00";
|
|
||||||
pub const BUSTYPE_MPSA: &'static [u8; 5usize] = b"MPSA\x00";
|
|
||||||
pub const BUSTYPE_NUBUS: &'static [u8; 6usize] = b"NUBUS\x00";
|
|
||||||
pub const BUSTYPE_TC: &'static [u8; 3usize] = b"TC\x00";
|
|
||||||
pub const BUSTYPE_VME: &'static [u8; 4usize] = b"VME\x00";
|
|
||||||
pub const BUSTYPE_XPRESS: &'static [u8; 7usize] = b"XPRESS\x00";
|
|
||||||
pub const MPC_APIC_USABLE: ::std::os::raw::c_uint = 1;
|
|
||||||
pub const MP_IRQDIR_DEFAULT: ::std::os::raw::c_uint = 0;
|
|
||||||
pub const MP_IRQDIR_HIGH: ::std::os::raw::c_uint = 1;
|
|
||||||
pub const MP_IRQDIR_LOW: ::std::os::raw::c_uint = 3;
|
|
||||||
pub const MP_APIC_ALL: ::std::os::raw::c_uint = 255;
|
|
||||||
pub const MPC_OEM_SIGNATURE: &'static [u8; 5usize] = b"_OEM\x00";
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Default, Copy)]
|
|
||||||
pub struct mpf_intel {
|
|
||||||
pub signature: [::std::os::raw::c_char; 4usize],
|
|
||||||
pub physptr: ::std::os::raw::c_uint,
|
|
||||||
pub length: ::std::os::raw::c_uchar,
|
|
||||||
pub specification: ::std::os::raw::c_uchar,
|
|
||||||
pub checksum: ::std::os::raw::c_uchar,
|
|
||||||
pub feature1: ::std::os::raw::c_uchar,
|
|
||||||
pub feature2: ::std::os::raw::c_uchar,
|
|
||||||
pub feature3: ::std::os::raw::c_uchar,
|
|
||||||
pub feature4: ::std::os::raw::c_uchar,
|
|
||||||
pub feature5: ::std::os::raw::c_uchar,
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_mpf_intel() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<mpf_intel>(),
|
|
||||||
16usize,
|
|
||||||
concat!("Size of: ", stringify!(mpf_intel))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<mpf_intel>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Alignment of ", stringify!(mpf_intel))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpf_intel>()).signature as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpf_intel),
|
|
||||||
"::",
|
|
||||||
stringify!(signature)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpf_intel>()).physptr as *const _ as usize },
|
|
||||||
4usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpf_intel),
|
|
||||||
"::",
|
|
||||||
stringify!(physptr)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpf_intel>()).length as *const _ as usize },
|
|
||||||
8usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpf_intel),
|
|
||||||
"::",
|
|
||||||
stringify!(length)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpf_intel>()).specification as *const _ as usize },
|
|
||||||
9usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpf_intel),
|
|
||||||
"::",
|
|
||||||
stringify!(specification)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpf_intel>()).checksum as *const _ as usize },
|
|
||||||
10usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpf_intel),
|
|
||||||
"::",
|
|
||||||
stringify!(checksum)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpf_intel>()).feature1 as *const _ as usize },
|
|
||||||
11usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpf_intel),
|
|
||||||
"::",
|
|
||||||
stringify!(feature1)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpf_intel>()).feature2 as *const _ as usize },
|
|
||||||
12usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpf_intel),
|
|
||||||
"::",
|
|
||||||
stringify!(feature2)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpf_intel>()).feature3 as *const _ as usize },
|
|
||||||
13usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpf_intel),
|
|
||||||
"::",
|
|
||||||
stringify!(feature3)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpf_intel>()).feature4 as *const _ as usize },
|
|
||||||
14usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpf_intel),
|
|
||||||
"::",
|
|
||||||
stringify!(feature4)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpf_intel>()).feature5 as *const _ as usize },
|
|
||||||
15usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpf_intel),
|
|
||||||
"::",
|
|
||||||
stringify!(feature5)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for mpf_intel {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Default, Copy)]
|
|
||||||
pub struct mpc_table {
|
|
||||||
pub signature: [::std::os::raw::c_char; 4usize],
|
|
||||||
pub length: ::std::os::raw::c_ushort,
|
|
||||||
pub spec: ::std::os::raw::c_char,
|
|
||||||
pub checksum: ::std::os::raw::c_char,
|
|
||||||
pub oem: [::std::os::raw::c_char; 8usize],
|
|
||||||
pub productid: [::std::os::raw::c_char; 12usize],
|
|
||||||
pub oemptr: ::std::os::raw::c_uint,
|
|
||||||
pub oemsize: ::std::os::raw::c_ushort,
|
|
||||||
pub oemcount: ::std::os::raw::c_ushort,
|
|
||||||
pub lapic: ::std::os::raw::c_uint,
|
|
||||||
pub reserved: ::std::os::raw::c_uint,
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_mpc_table() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<mpc_table>(),
|
|
||||||
44usize,
|
|
||||||
concat!("Size of: ", stringify!(mpc_table))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<mpc_table>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Alignment of ", stringify!(mpc_table))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_table>()).signature as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_table),
|
|
||||||
"::",
|
|
||||||
stringify!(signature)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_table>()).length as *const _ as usize },
|
|
||||||
4usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_table),
|
|
||||||
"::",
|
|
||||||
stringify!(length)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_table>()).spec as *const _ as usize },
|
|
||||||
6usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_table),
|
|
||||||
"::",
|
|
||||||
stringify!(spec)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_table>()).checksum as *const _ as usize },
|
|
||||||
7usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_table),
|
|
||||||
"::",
|
|
||||||
stringify!(checksum)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_table>()).oem as *const _ as usize },
|
|
||||||
8usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_table),
|
|
||||||
"::",
|
|
||||||
stringify!(oem)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_table>()).productid as *const _ as usize },
|
|
||||||
16usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_table),
|
|
||||||
"::",
|
|
||||||
stringify!(productid)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_table>()).oemptr as *const _ as usize },
|
|
||||||
28usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_table),
|
|
||||||
"::",
|
|
||||||
stringify!(oemptr)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_table>()).oemsize as *const _ as usize },
|
|
||||||
32usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_table),
|
|
||||||
"::",
|
|
||||||
stringify!(oemsize)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_table>()).oemcount as *const _ as usize },
|
|
||||||
34usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_table),
|
|
||||||
"::",
|
|
||||||
stringify!(oemcount)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_table>()).lapic as *const _ as usize },
|
|
||||||
36usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_table),
|
|
||||||
"::",
|
|
||||||
stringify!(lapic)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_table>()).reserved as *const _ as usize },
|
|
||||||
40usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_table),
|
|
||||||
"::",
|
|
||||||
stringify!(reserved)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for mpc_table {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Default, Copy)]
|
|
||||||
pub struct mpc_cpu {
|
|
||||||
pub type_: ::std::os::raw::c_uchar,
|
|
||||||
pub apicid: ::std::os::raw::c_uchar,
|
|
||||||
pub apicver: ::std::os::raw::c_uchar,
|
|
||||||
pub cpuflag: ::std::os::raw::c_uchar,
|
|
||||||
pub cpufeature: ::std::os::raw::c_uint,
|
|
||||||
pub featureflag: ::std::os::raw::c_uint,
|
|
||||||
pub reserved: [::std::os::raw::c_uint; 2usize],
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_mpc_cpu() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<mpc_cpu>(),
|
|
||||||
20usize,
|
|
||||||
concat!("Size of: ", stringify!(mpc_cpu))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<mpc_cpu>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Alignment of ", stringify!(mpc_cpu))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_cpu>()).type_ as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_cpu),
|
|
||||||
"::",
|
|
||||||
stringify!(type_)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_cpu>()).apicid as *const _ as usize },
|
|
||||||
1usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_cpu),
|
|
||||||
"::",
|
|
||||||
stringify!(apicid)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_cpu>()).apicver as *const _ as usize },
|
|
||||||
2usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_cpu),
|
|
||||||
"::",
|
|
||||||
stringify!(apicver)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_cpu>()).cpuflag as *const _ as usize },
|
|
||||||
3usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_cpu),
|
|
||||||
"::",
|
|
||||||
stringify!(cpuflag)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_cpu>()).cpufeature as *const _ as usize },
|
|
||||||
4usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_cpu),
|
|
||||||
"::",
|
|
||||||
stringify!(cpufeature)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_cpu>()).featureflag as *const _ as usize },
|
|
||||||
8usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_cpu),
|
|
||||||
"::",
|
|
||||||
stringify!(featureflag)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_cpu>()).reserved as *const _ as usize },
|
|
||||||
12usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_cpu),
|
|
||||||
"::",
|
|
||||||
stringify!(reserved)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for mpc_cpu {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Default, Copy)]
|
|
||||||
pub struct mpc_bus {
|
|
||||||
pub type_: ::std::os::raw::c_uchar,
|
|
||||||
pub busid: ::std::os::raw::c_uchar,
|
|
||||||
pub bustype: [::std::os::raw::c_uchar; 6usize],
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_mpc_bus() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<mpc_bus>(),
|
|
||||||
8usize,
|
|
||||||
concat!("Size of: ", stringify!(mpc_bus))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<mpc_bus>(),
|
|
||||||
1usize,
|
|
||||||
concat!("Alignment of ", stringify!(mpc_bus))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_bus>()).type_ as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_bus),
|
|
||||||
"::",
|
|
||||||
stringify!(type_)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_bus>()).busid as *const _ as usize },
|
|
||||||
1usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_bus),
|
|
||||||
"::",
|
|
||||||
stringify!(busid)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_bus>()).bustype as *const _ as usize },
|
|
||||||
2usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_bus),
|
|
||||||
"::",
|
|
||||||
stringify!(bustype)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for mpc_bus {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Default, Copy)]
|
|
||||||
pub struct mpc_ioapic {
|
|
||||||
pub type_: ::std::os::raw::c_uchar,
|
|
||||||
pub apicid: ::std::os::raw::c_uchar,
|
|
||||||
pub apicver: ::std::os::raw::c_uchar,
|
|
||||||
pub flags: ::std::os::raw::c_uchar,
|
|
||||||
pub apicaddr: ::std::os::raw::c_uint,
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_mpc_ioapic() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<mpc_ioapic>(),
|
|
||||||
8usize,
|
|
||||||
concat!("Size of: ", stringify!(mpc_ioapic))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<mpc_ioapic>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Alignment of ", stringify!(mpc_ioapic))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_ioapic>()).type_ as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_ioapic),
|
|
||||||
"::",
|
|
||||||
stringify!(type_)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_ioapic>()).apicid as *const _ as usize },
|
|
||||||
1usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_ioapic),
|
|
||||||
"::",
|
|
||||||
stringify!(apicid)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_ioapic>()).apicver as *const _ as usize },
|
|
||||||
2usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_ioapic),
|
|
||||||
"::",
|
|
||||||
stringify!(apicver)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_ioapic>()).flags as *const _ as usize },
|
|
||||||
3usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_ioapic),
|
|
||||||
"::",
|
|
||||||
stringify!(flags)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_ioapic>()).apicaddr as *const _ as usize },
|
|
||||||
4usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_ioapic),
|
|
||||||
"::",
|
|
||||||
stringify!(apicaddr)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for mpc_ioapic {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Default, Copy)]
|
|
||||||
pub struct mpc_intsrc {
|
|
||||||
pub type_: ::std::os::raw::c_uchar,
|
|
||||||
pub irqtype: ::std::os::raw::c_uchar,
|
|
||||||
pub irqflag: ::std::os::raw::c_ushort,
|
|
||||||
pub srcbus: ::std::os::raw::c_uchar,
|
|
||||||
pub srcbusirq: ::std::os::raw::c_uchar,
|
|
||||||
pub dstapic: ::std::os::raw::c_uchar,
|
|
||||||
pub dstirq: ::std::os::raw::c_uchar,
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_mpc_intsrc() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<mpc_intsrc>(),
|
|
||||||
8usize,
|
|
||||||
concat!("Size of: ", stringify!(mpc_intsrc))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<mpc_intsrc>(),
|
|
||||||
2usize,
|
|
||||||
concat!("Alignment of ", stringify!(mpc_intsrc))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_intsrc>()).type_ as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_intsrc),
|
|
||||||
"::",
|
|
||||||
stringify!(type_)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_intsrc>()).irqtype as *const _ as usize },
|
|
||||||
1usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_intsrc),
|
|
||||||
"::",
|
|
||||||
stringify!(irqtype)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_intsrc>()).irqflag as *const _ as usize },
|
|
||||||
2usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_intsrc),
|
|
||||||
"::",
|
|
||||||
stringify!(irqflag)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_intsrc>()).srcbus as *const _ as usize },
|
|
||||||
4usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_intsrc),
|
|
||||||
"::",
|
|
||||||
stringify!(srcbus)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_intsrc>()).srcbusirq as *const _ as usize },
|
|
||||||
5usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_intsrc),
|
|
||||||
"::",
|
|
||||||
stringify!(srcbusirq)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_intsrc>()).dstapic as *const _ as usize },
|
|
||||||
6usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_intsrc),
|
|
||||||
"::",
|
|
||||||
stringify!(dstapic)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_intsrc>()).dstirq as *const _ as usize },
|
|
||||||
7usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_intsrc),
|
|
||||||
"::",
|
|
||||||
stringify!(dstirq)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for mpc_intsrc {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub const mp_irq_source_types_mp_INT: mp_irq_source_types = 0;
|
|
||||||
pub const mp_irq_source_types_mp_NMI: mp_irq_source_types = 1;
|
|
||||||
pub const mp_irq_source_types_mp_SMI: mp_irq_source_types = 2;
|
|
||||||
pub const mp_irq_source_types_mp_ExtINT: mp_irq_source_types = 3;
|
|
||||||
pub type mp_irq_source_types = ::std::os::raw::c_uint;
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Default, Copy)]
|
|
||||||
pub struct mpc_lintsrc {
|
|
||||||
pub type_: ::std::os::raw::c_uchar,
|
|
||||||
pub irqtype: ::std::os::raw::c_uchar,
|
|
||||||
pub irqflag: ::std::os::raw::c_ushort,
|
|
||||||
pub srcbusid: ::std::os::raw::c_uchar,
|
|
||||||
pub srcbusirq: ::std::os::raw::c_uchar,
|
|
||||||
pub destapic: ::std::os::raw::c_uchar,
|
|
||||||
pub destapiclint: ::std::os::raw::c_uchar,
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_mpc_lintsrc() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<mpc_lintsrc>(),
|
|
||||||
8usize,
|
|
||||||
concat!("Size of: ", stringify!(mpc_lintsrc))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<mpc_lintsrc>(),
|
|
||||||
2usize,
|
|
||||||
concat!("Alignment of ", stringify!(mpc_lintsrc))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).type_ as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_lintsrc),
|
|
||||||
"::",
|
|
||||||
stringify!(type_)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).irqtype as *const _ as usize },
|
|
||||||
1usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_lintsrc),
|
|
||||||
"::",
|
|
||||||
stringify!(irqtype)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).irqflag as *const _ as usize },
|
|
||||||
2usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_lintsrc),
|
|
||||||
"::",
|
|
||||||
stringify!(irqflag)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).srcbusid as *const _ as usize },
|
|
||||||
4usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_lintsrc),
|
|
||||||
"::",
|
|
||||||
stringify!(srcbusid)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).srcbusirq as *const _ as usize },
|
|
||||||
5usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_lintsrc),
|
|
||||||
"::",
|
|
||||||
stringify!(srcbusirq)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).destapic as *const _ as usize },
|
|
||||||
6usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_lintsrc),
|
|
||||||
"::",
|
|
||||||
stringify!(destapic)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).destapiclint as *const _ as usize },
|
|
||||||
7usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_lintsrc),
|
|
||||||
"::",
|
|
||||||
stringify!(destapiclint)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for mpc_lintsrc {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Default, Copy)]
|
|
||||||
pub struct mpc_oemtable {
|
|
||||||
pub signature: [::std::os::raw::c_char; 4usize],
|
|
||||||
pub length: ::std::os::raw::c_ushort,
|
|
||||||
pub rev: ::std::os::raw::c_char,
|
|
||||||
pub checksum: ::std::os::raw::c_char,
|
|
||||||
pub mpc: [::std::os::raw::c_char; 8usize],
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_mpc_oemtable() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<mpc_oemtable>(),
|
|
||||||
16usize,
|
|
||||||
concat!("Size of: ", stringify!(mpc_oemtable))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<mpc_oemtable>(),
|
|
||||||
2usize,
|
|
||||||
concat!("Alignment of ", stringify!(mpc_oemtable))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_oemtable>()).signature as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_oemtable),
|
|
||||||
"::",
|
|
||||||
stringify!(signature)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_oemtable>()).length as *const _ as usize },
|
|
||||||
4usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_oemtable),
|
|
||||||
"::",
|
|
||||||
stringify!(length)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_oemtable>()).rev as *const _ as usize },
|
|
||||||
6usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_oemtable),
|
|
||||||
"::",
|
|
||||||
stringify!(rev)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_oemtable>()).checksum as *const _ as usize },
|
|
||||||
7usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_oemtable),
|
|
||||||
"::",
|
|
||||||
stringify!(checksum)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*std::ptr::null::<mpc_oemtable>()).mpc as *const _ as usize },
|
|
||||||
8usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(mpc_oemtable),
|
|
||||||
"::",
|
|
||||||
stringify!(mpc)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for mpc_oemtable {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub const mp_bustype_MP_BUS_ISA: mp_bustype = 1;
|
|
||||||
pub const mp_bustype_MP_BUS_EISA: mp_bustype = 2;
|
|
||||||
pub const mp_bustype_MP_BUS_PCI: mp_bustype = 3;
|
|
||||||
pub type mp_bustype = ::std::os::raw::c_uint;
|
|
||||||
@@ -10,15 +10,14 @@ io_uring = []
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
io-uring = ">=0.4.0"
|
io-uring = ">=0.4.0"
|
||||||
libc = "0.2.94"
|
libc = "0.2.96"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
qcow = { path = "../qcow" }
|
qcow = { path = "../qcow" }
|
||||||
serde = ">=1.0.27"
|
|
||||||
serde_derive = ">=1.0.27"
|
|
||||||
serde_json = ">=1.0.9"
|
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
versionize = "0.1.6"
|
||||||
|
versionize_derive = "0.1.4"
|
||||||
virtio-bindings = { version = "0.1", features = ["virtio-v5_0_0"]}
|
virtio-bindings = { version = "0.1", features = ["virtio-v5_0_0"]}
|
||||||
vm-memory = { version = "0.5.0", features = ["backend-mmap", "backend-atomic"] }
|
vm-memory = { version = "0.5.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
vmm-sys-util = ">=0.3.1"
|
vmm-sys-util = ">=0.3.1"
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
#[macro_use]
|
|
||||||
extern crate serde_derive;
|
|
||||||
|
|
||||||
pub mod async_io;
|
pub mod async_io;
|
||||||
pub mod fixed_vhd_async;
|
pub mod fixed_vhd_async;
|
||||||
@@ -34,11 +32,18 @@ use std::os::unix::io::AsRawFd;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||||
|
use versionize_derive::Versionize;
|
||||||
use virtio_bindings::bindings::virtio_blk::*;
|
use virtio_bindings::bindings::virtio_blk::*;
|
||||||
use vm_memory::{ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryError, GuestMemoryMmap};
|
use vm_memory::{
|
||||||
|
bitmap::AtomicBitmap, bitmap::Bitmap, ByteValued, Bytes, GuestAddress, GuestMemory,
|
||||||
|
GuestMemoryError,
|
||||||
|
};
|
||||||
use vm_virtio::DescriptorChain;
|
use vm_virtio::DescriptorChain;
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
|
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
|
||||||
|
|
||||||
const SECTOR_SHIFT: u8 = 9;
|
const SECTOR_SHIFT: u8 = 9;
|
||||||
pub const SECTOR_SIZE: u64 = 0x01 << SECTOR_SHIFT;
|
pub const SECTOR_SIZE: u64 = 0x01 << SECTOR_SHIFT;
|
||||||
|
|
||||||
@@ -331,6 +336,12 @@ impl Request {
|
|||||||
// Queue operations expected to be submitted.
|
// Queue operations expected to be submitted.
|
||||||
match request_type {
|
match request_type {
|
||||||
RequestType::In => {
|
RequestType::In => {
|
||||||
|
for (data_addr, data_len) in &self.data_descriptors {
|
||||||
|
mem.get_slice(*data_addr, *data_len as usize)
|
||||||
|
.map_err(ExecuteError::GetHostAddress)?
|
||||||
|
.bitmap()
|
||||||
|
.mark_dirty(0, *data_len as usize);
|
||||||
|
}
|
||||||
disk_image
|
disk_image
|
||||||
.read_vectored(offset, iovecs, user_data)
|
.read_vectored(offset, iovecs, user_data)
|
||||||
.map_err(ExecuteError::AsyncRead)?;
|
.map_err(ExecuteError::AsyncRead)?;
|
||||||
@@ -369,7 +380,7 @@ impl Request {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, Deserialize, Serialize)]
|
#[derive(Copy, Clone, Debug, Default, Versionize)]
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
pub struct VirtioBlockConfig {
|
pub struct VirtioBlockConfig {
|
||||||
pub capacity: u64,
|
pub capacity: u64,
|
||||||
@@ -394,7 +405,7 @@ pub struct VirtioBlockConfig {
|
|||||||
}
|
}
|
||||||
unsafe impl ByteValued for VirtioBlockConfig {}
|
unsafe impl ByteValued for VirtioBlockConfig {}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, Default, Versionize)]
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
pub struct VirtioBlockGeometry {
|
pub struct VirtioBlockGeometry {
|
||||||
pub cylinders: u16,
|
pub cylinders: u16,
|
||||||
|
|||||||
@@ -2,19 +2,20 @@
|
|||||||
name = "devices"
|
name = "devices"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["The Chromium OS Authors"]
|
authors = ["The Chromium OS Authors"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
acpi_tables = { path = "../acpi_tables", optional = true }
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
|
arch = { path = "../arch" }
|
||||||
bitflags = ">=1.2.1"
|
bitflags = ">=1.2.1"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
epoll = ">=4.0.1"
|
epoll = ">=4.0.1"
|
||||||
libc = "0.2.94"
|
libc = "0.2.96"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
serde = {version = ">=1.0.27", features = ["rc"] }
|
versionize = "0.1.6"
|
||||||
serde_derive = ">=1.0.27"
|
versionize_derive = "0.1.4"
|
||||||
serde_json = ">=1.0.9"
|
|
||||||
vm-device = { path = "../vm-device" }
|
vm-device = { path = "../vm-device" }
|
||||||
acpi_tables = { path = "../acpi_tables", optional = true }
|
|
||||||
vm-memory = "0.5.0"
|
vm-memory = "0.5.0"
|
||||||
vm-migration = { path = "../vm-migration" }
|
vm-migration = { path = "../vm-migration" }
|
||||||
vmm-sys-util = ">=0.3.1"
|
vmm-sys-util = ">=0.3.1"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
//
|
//
|
||||||
|
|
||||||
|
use super::AcpiNotificationFlags;
|
||||||
use acpi_tables::{aml, aml::Aml};
|
use acpi_tables::{aml, aml::Aml};
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{Arc, Barrier};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
@@ -10,7 +11,6 @@ use vm_device::interrupt::InterruptSourceGroup;
|
|||||||
use vm_device::BusDevice;
|
use vm_device::BusDevice;
|
||||||
use vm_memory::GuestAddress;
|
use vm_memory::GuestAddress;
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
use AcpiNotificationFlags;
|
|
||||||
|
|
||||||
pub const GED_DEVICE_ACPI_SIZE: usize = 0x1;
|
pub const GED_DEVICE_ACPI_SIZE: usize = 0x1;
|
||||||
|
|
||||||
@@ -52,7 +52,6 @@ impl BusDevice for AcpiShutdownDevice {
|
|||||||
const SLEEP_VALUE_BIT: u8 = 2;
|
const SLEEP_VALUE_BIT: u8 = 2;
|
||||||
if data[0] == (S5_SLEEP_VALUE << SLEEP_VALUE_BIT) | (1 << SLEEP_STATUS_EN_BIT) {
|
if data[0] == (S5_SLEEP_VALUE << SLEEP_VALUE_BIT) | (1 << SLEEP_STATUS_EN_BIT) {
|
||||||
debug!("ACPI Shutdown signalled");
|
debug!("ACPI Shutdown signalled");
|
||||||
extern crate bitflags;
|
|
||||||
if let Err(e) = self.exit_evt.write(1) {
|
if let Err(e) = self.exit_evt.write(1) {
|
||||||
error!("Error triggering ACPI shutdown event: {}", e);
|
error!("Error triggering ACPI shutdown event: {}", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||||
|
|
||||||
use super::interrupt_controller::{Error, InterruptController};
|
use super::interrupt_controller::{Error, InterruptController};
|
||||||
|
extern crate arch;
|
||||||
|
use arch::aarch64::gic::GicDevice;
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, Mutex};
|
||||||
use vm_device::interrupt::{
|
use vm_device::interrupt::{
|
||||||
InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup,
|
InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup,
|
||||||
LegacyIrqSourceConfig, MsiIrqGroupConfig,
|
LegacyIrqSourceConfig, MsiIrqGroupConfig,
|
||||||
@@ -14,7 +16,7 @@ use vmm_sys_util::eventfd::EventFd;
|
|||||||
type Result<T> = result::Result<T, Error>;
|
type Result<T> = result::Result<T, Error>;
|
||||||
|
|
||||||
// Reserve 32 IRQs for legacy device.
|
// Reserve 32 IRQs for legacy device.
|
||||||
pub const IRQ_LEGACY_BASE: usize = 0;
|
pub const IRQ_LEGACY_BASE: usize = arch::layout::IRQ_BASE as usize;
|
||||||
pub const IRQ_LEGACY_COUNT: usize = 32;
|
pub const IRQ_LEGACY_COUNT: usize = 32;
|
||||||
|
|
||||||
// This Gic struct implements InterruptController to provide interrupt delivery service.
|
// This Gic struct implements InterruptController to provide interrupt delivery service.
|
||||||
@@ -25,6 +27,7 @@ pub const IRQ_LEGACY_COUNT: usize = 32;
|
|||||||
// 2. Move this file and ioapic.rs to arch/, as they are architecture specific.
|
// 2. Move this file and ioapic.rs to arch/, as they are architecture specific.
|
||||||
pub struct Gic {
|
pub struct Gic {
|
||||||
interrupt_source_group: Arc<Box<dyn InterruptSourceGroup>>,
|
interrupt_source_group: Arc<Box<dyn InterruptSourceGroup>>,
|
||||||
|
gic_device: Option<Arc<Mutex<Box<dyn GicDevice>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Gic {
|
impl Gic {
|
||||||
@@ -41,8 +44,17 @@ impl Gic {
|
|||||||
|
|
||||||
Ok(Gic {
|
Ok(Gic {
|
||||||
interrupt_source_group,
|
interrupt_source_group,
|
||||||
|
gic_device: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_gic_device(&mut self, gic_device: Arc<Mutex<Box<dyn GicDevice>>>) {
|
||||||
|
self.gic_device = Some(gic_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_gic_device(&self) -> Option<&Arc<Mutex<Box<dyn GicDevice>>>> {
|
||||||
|
self.gic_device.as_ref()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InterruptController for Gic {
|
impl InterruptController for Gic {
|
||||||
@@ -58,7 +70,7 @@ impl InterruptController for Gic {
|
|||||||
for i in IRQ_LEGACY_BASE..(IRQ_LEGACY_BASE + IRQ_LEGACY_COUNT) {
|
for i in IRQ_LEGACY_BASE..(IRQ_LEGACY_BASE + IRQ_LEGACY_COUNT) {
|
||||||
let config = LegacyIrqSourceConfig {
|
let config = LegacyIrqSourceConfig {
|
||||||
irqchip: 0,
|
irqchip: 0,
|
||||||
pin: i as u32,
|
pin: (i - IRQ_LEGACY_BASE) as u32,
|
||||||
};
|
};
|
||||||
self.interrupt_source_group
|
self.interrupt_source_group
|
||||||
.update(
|
.update(
|
||||||
|
|||||||
@@ -14,13 +14,17 @@ use anyhow::anyhow;
|
|||||||
use byteorder::{ByteOrder, LittleEndian};
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{Arc, Barrier};
|
||||||
|
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||||
|
use versionize_derive::Versionize;
|
||||||
use vm_device::interrupt::{
|
use vm_device::interrupt::{
|
||||||
InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup,
|
InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup,
|
||||||
MsiIrqGroupConfig, MsiIrqSourceConfig,
|
MsiIrqGroupConfig, MsiIrqSourceConfig,
|
||||||
};
|
};
|
||||||
use vm_device::BusDevice;
|
use vm_device::BusDevice;
|
||||||
use vm_memory::GuestAddress;
|
use vm_memory::GuestAddress;
|
||||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
use vm_migration::{
|
||||||
|
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||||
|
};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
type Result<T> = result::Result<T, Error>;
|
type Result<T> = result::Result<T, Error>;
|
||||||
@@ -133,7 +137,7 @@ pub struct Ioapic {
|
|||||||
interrupt_source_group: Arc<Box<dyn InterruptSourceGroup>>,
|
interrupt_source_group: Arc<Box<dyn InterruptSourceGroup>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Versionize)]
|
||||||
pub struct IoapicState {
|
pub struct IoapicState {
|
||||||
id_reg: u32,
|
id_reg: u32,
|
||||||
reg_sel: u32,
|
reg_sel: u32,
|
||||||
@@ -141,6 +145,7 @@ pub struct IoapicState {
|
|||||||
used_entries: [bool; NUM_IOAPIC_PINS],
|
used_entries: [bool; NUM_IOAPIC_PINS],
|
||||||
apic_address: u64,
|
apic_address: u64,
|
||||||
}
|
}
|
||||||
|
impl VersionMapped for IoapicState {}
|
||||||
|
|
||||||
impl BusDevice for Ioapic {
|
impl BusDevice for Ioapic {
|
||||||
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
|
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
|
||||||
@@ -410,13 +415,18 @@ impl Snapshottable for Ioapic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||||
Snapshot::new_from_state(&self.id, &self.state())
|
Snapshot::new_from_versioned_state(&self.id, &self.state())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
|
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
|
||||||
self.set_state(&snapshot.to_state(&self.id)?).map_err(|e| {
|
self.set_state(&snapshot.to_versioned_state(&self.id)?)
|
||||||
MigratableError::Restore(anyhow!("Could not restore state for {}: {:?}", self.id, e))
|
.map_err(|e| {
|
||||||
})
|
MigratableError::Restore(anyhow!(
|
||||||
|
"Could not restore state for {}: {:?}",
|
||||||
|
self.id,
|
||||||
|
e
|
||||||
|
))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,13 @@ use crate::{read_le_u32, write_le_u32};
|
|||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{Arc, Barrier};
|
||||||
use std::{fmt, io};
|
use std::{fmt, io};
|
||||||
|
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||||
|
use versionize_derive::Versionize;
|
||||||
use vm_device::interrupt::InterruptSourceGroup;
|
use vm_device::interrupt::InterruptSourceGroup;
|
||||||
use vm_device::BusDevice;
|
use vm_device::BusDevice;
|
||||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
use vm_migration::{
|
||||||
|
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||||
|
};
|
||||||
|
|
||||||
const OFS_DATA: u64 = 0x400; // Data Register
|
const OFS_DATA: u64 = 0x400; // Data Register
|
||||||
const GPIODIR: u64 = 0x400; // Direction Register
|
const GPIODIR: u64 = 0x400; // Direction Register
|
||||||
@@ -85,7 +89,7 @@ pub struct Gpio {
|
|||||||
interrupt: Arc<Box<dyn InterruptSourceGroup>>,
|
interrupt: Arc<Box<dyn InterruptSourceGroup>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Versionize)]
|
||||||
pub struct GpioState {
|
pub struct GpioState {
|
||||||
data: u32,
|
data: u32,
|
||||||
old_in_data: u32,
|
old_in_data: u32,
|
||||||
@@ -98,6 +102,8 @@ pub struct GpioState {
|
|||||||
afsel: u32,
|
afsel: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl VersionMapped for GpioState {}
|
||||||
|
|
||||||
impl Gpio {
|
impl Gpio {
|
||||||
/// Constructs an PL061 GPIO device.
|
/// Constructs an PL061 GPIO device.
|
||||||
pub fn new(id: String, interrupt: Arc<Box<dyn InterruptSourceGroup>>) -> Self {
|
pub fn new(id: String, interrupt: Arc<Box<dyn InterruptSourceGroup>>) -> Self {
|
||||||
@@ -313,11 +319,11 @@ impl Snapshottable for Gpio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||||
Snapshot::new_from_state(&self.id, &self.state())
|
Snapshot::new_from_versioned_state(&self.id, &self.state())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
|
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
|
||||||
self.set_state(&snapshot.to_state(&self.id)?);
|
self.set_state(&snapshot.to_versioned_state(&self.id)?);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,13 @@
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{Arc, Barrier};
|
||||||
use std::{io, result};
|
use std::{io, result};
|
||||||
|
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||||
|
use versionize_derive::Versionize;
|
||||||
use vm_device::interrupt::InterruptSourceGroup;
|
use vm_device::interrupt::InterruptSourceGroup;
|
||||||
use vm_device::BusDevice;
|
use vm_device::BusDevice;
|
||||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
use vm_migration::{
|
||||||
|
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||||
|
};
|
||||||
use vmm_sys_util::errno::Result;
|
use vmm_sys_util::errno::Result;
|
||||||
|
|
||||||
const LOOP_SIZE: usize = 0x40;
|
const LOOP_SIZE: usize = 0x40;
|
||||||
@@ -70,7 +74,7 @@ pub struct Serial {
|
|||||||
out: Option<Box<dyn io::Write + Send>>,
|
out: Option<Box<dyn io::Write + Send>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Versionize)]
|
||||||
pub struct SerialState {
|
pub struct SerialState {
|
||||||
interrupt_enable: u8,
|
interrupt_enable: u8,
|
||||||
interrupt_identification: u8,
|
interrupt_identification: u8,
|
||||||
@@ -82,6 +86,7 @@ pub struct SerialState {
|
|||||||
baud_divisor: u16,
|
baud_divisor: u16,
|
||||||
in_buffer: Vec<u8>,
|
in_buffer: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
impl VersionMapped for SerialState {}
|
||||||
|
|
||||||
impl Serial {
|
impl Serial {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
@@ -288,11 +293,11 @@ impl Snapshottable for Serial {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||||
Snapshot::new_from_state(&self.id, &self.state())
|
Snapshot::new_from_versioned_state(&self.id, &self.state())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
|
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
|
||||||
self.set_state(&snapshot.to_state(&self.id)?);
|
self.set_state(&snapshot.to_versioned_state(&self.id)?);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,13 @@ use std::collections::VecDeque;
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{Arc, Barrier};
|
||||||
use std::{io, result};
|
use std::{io, result};
|
||||||
|
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||||
|
use versionize_derive::Versionize;
|
||||||
use vm_device::interrupt::InterruptSourceGroup;
|
use vm_device::interrupt::InterruptSourceGroup;
|
||||||
use vm_device::BusDevice;
|
use vm_device::BusDevice;
|
||||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
use vm_migration::{
|
||||||
|
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||||
|
};
|
||||||
|
|
||||||
/* Registers */
|
/* Registers */
|
||||||
const UARTDR: u64 = 0;
|
const UARTDR: u64 = 0;
|
||||||
@@ -86,7 +90,7 @@ pub struct Pl011 {
|
|||||||
out: Option<Box<dyn io::Write + Send>>,
|
out: Option<Box<dyn io::Write + Send>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Versionize)]
|
||||||
pub struct Pl011State {
|
pub struct Pl011State {
|
||||||
flags: u32,
|
flags: u32,
|
||||||
lcr: u32,
|
lcr: u32,
|
||||||
@@ -104,6 +108,8 @@ pub struct Pl011State {
|
|||||||
read_trigger: u32,
|
read_trigger: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl VersionMapped for Pl011State {}
|
||||||
|
|
||||||
impl Pl011 {
|
impl Pl011 {
|
||||||
/// Constructs an AMBA PL011 UART device.
|
/// Constructs an AMBA PL011 UART device.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
@@ -357,11 +363,11 @@ impl Snapshottable for Pl011 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||||
Snapshot::new_from_state(&self.id, &self.state())
|
Snapshot::new_from_versioned_state(&self.id, &self.state())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
|
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
|
||||||
self.set_state(&snapshot.to_state(&self.id)?);
|
self.set_state(&snapshot.to_versioned_state(&self.id)?);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,24 +6,11 @@
|
|||||||
// found in the LICENSE-BSD-3-Clause file.
|
// found in the LICENSE-BSD-3-Clause file.
|
||||||
|
|
||||||
//! Emulates virtual and hardware devices.
|
//! Emulates virtual and hardware devices.
|
||||||
extern crate anyhow;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
extern crate byteorder;
|
|
||||||
extern crate epoll;
|
|
||||||
extern crate libc;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
#[cfg(feature = "acpi")]
|
|
||||||
extern crate acpi_tables;
|
|
||||||
extern crate serde;
|
|
||||||
extern crate vm_device;
|
|
||||||
extern crate vm_memory;
|
|
||||||
extern crate vm_migration;
|
|
||||||
extern crate vmm_sys_util;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate serde_derive;
|
|
||||||
extern crate serde_json;
|
|
||||||
|
|
||||||
#[cfg(feature = "acpi")]
|
#[cfg(feature = "acpi")]
|
||||||
pub mod acpi;
|
pub mod acpi;
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ Ubuntu distributions.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
apt update
|
apt update
|
||||||
apt install fio iperf iperf3 socat
|
apt install fio iperf iperf3 socat stress
|
||||||
```
|
```
|
||||||
|
|
||||||
### Remove counterproductive packages
|
### Remove counterproductive packages
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ $ ./cloud-hypervisor/target/release/cloud-hypervisor \
|
|||||||
$ popd
|
$ popd
|
||||||
```
|
```
|
||||||
|
|
||||||
Notice the addition of `--api-socket=/tmp/ch-socket` and a `max` parameter on `--cpus boot=4.max=8`.
|
Notice the addition of `--api-socket=/tmp/ch-socket` and a `max` parameter on `--cpus boot=4,max=8`.
|
||||||
|
|
||||||
To ask the VMM to add additional vCPUs then use the resize API:
|
To ask the VMM to add additional vCPUs then use the resize API:
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ following [instructions](https://github.com/intel/linux-sgx).
|
|||||||
|
|
||||||
## Cloud-Hypervisor support
|
## Cloud-Hypervisor support
|
||||||
|
|
||||||
Assuming the host exposes `/dev/sgx_virt_epc`, we can pass SGX enclaves through
|
Assuming the host exposes `/dev/sgx_vepc`, we can pass SGX enclaves through
|
||||||
the guest.
|
the guest.
|
||||||
|
|
||||||
In order to use SGX enclaves within a Cloud-Hypervisor VM, we must define one
|
In order to use SGX enclaves within a Cloud-Hypervisor VM, we must define one
|
||||||
@@ -43,7 +43,7 @@ have been correctly created under `/dev/sgx`:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
ls /dev/sgx*
|
ls /dev/sgx*
|
||||||
/dev/sgx_enclave /dev/sgx_provision /dev/sgx_virt_epc
|
/dev/sgx_enclave /dev/sgx_provision /dev/sgx_vepc
|
||||||
```
|
```
|
||||||
|
|
||||||
From this point, it is possible to run any SGX application from the guest, as
|
From this point, it is possible to run any SGX application from the guest, as
|
||||||
@@ -51,5 +51,5 @@ it will access `/dev/sgx_enclave` device to create dedicated SGX enclaves.
|
|||||||
|
|
||||||
Note: There is only one contiguous SGX EPC region, which contains all SGX EPC
|
Note: There is only one contiguous SGX EPC region, which contains all SGX EPC
|
||||||
sections. This region is exposed through ACPI and marked as reserved through
|
sections. This region is exposed through ACPI and marked as reserved through
|
||||||
the e820 table. It is treated yet as another device, which means it should
|
the e820 table. It is treated as yet another device, which means it should
|
||||||
appear at the end of the guest address space.
|
appear at the end of the guest address space.
|
||||||
|
|||||||
139
docs/live_migration.md
Normal file
139
docs/live_migration.md
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
# Live Migration
|
||||||
|
|
||||||
|
This document gives two examples of how to use the live migration
|
||||||
|
support in Cloud Hypervisor:
|
||||||
|
|
||||||
|
1. local migration - migrating between two VMs running on the same
|
||||||
|
machine;
|
||||||
|
1. nested-vm migration - migrating between two nested VMs whose host VMs
|
||||||
|
are running on the same machine.
|
||||||
|
|
||||||
|
## Local Migration
|
||||||
|
Launch the source VM (on the host machine):
|
||||||
|
```bash
|
||||||
|
$ target/release/cloud-hypervisor
|
||||||
|
--kernel ~/workloads/vmlinux \
|
||||||
|
--disk path=~/workloads/focal.raw \
|
||||||
|
--cpus boot=1 --memory size=1G \
|
||||||
|
--cmdline "root=/dev/vda1 console=ttyS0" \
|
||||||
|
--serial tty --console off --api-socket=/tmp/api1
|
||||||
|
```
|
||||||
|
|
||||||
|
Launch the destination VM from the same directory (on the host machine):
|
||||||
|
```bash
|
||||||
|
$ target/release/cloud-hypervisor --api-socket=/tmp/api2
|
||||||
|
```
|
||||||
|
|
||||||
|
Get ready for receiving migration for the destination VM (on the host machine):
|
||||||
|
```bash
|
||||||
|
$ target/release/ch-remote --api-socket=/tmp/api2 receive-migration unix:/tmp/sock
|
||||||
|
```
|
||||||
|
|
||||||
|
Start to send migration for the source VM (on the host machine):
|
||||||
|
```bash
|
||||||
|
$ target/release/ch-remote --api-socket=/tmp/api1 send-migration unix:/tmp/sock
|
||||||
|
```
|
||||||
|
|
||||||
|
When the above commands completed, the source VM should be successfully
|
||||||
|
migrated to the destination VM. Now the destination VM is running while
|
||||||
|
the source VM is paused.
|
||||||
|
|
||||||
|
## Nested-VM Migration
|
||||||
|
|
||||||
|
Launch VM 1 (on the host machine) with an extra virtio-blk device for
|
||||||
|
exposing a guest image for the nested source VM:
|
||||||
|
> Note: the example below also attached an additional virtio-blk device
|
||||||
|
> with a dummy image for testing purpose (which is optional).
|
||||||
|
```bash
|
||||||
|
$ head -c 1M < /dev/urandom > tmp.img # create a dummy image for testing
|
||||||
|
$ sudo /target/release/cloud-hypervisor \
|
||||||
|
--serial tty --console off \
|
||||||
|
--cpus boot=1 --memory size=512M \
|
||||||
|
--kernel vmlinux \
|
||||||
|
--cmdline "root=/dev/vda1 console=ttyS0" \
|
||||||
|
--disk path=focal-1.raw path=focal-nested.raw path=tmp.img\
|
||||||
|
--net ip=192.168.101.1
|
||||||
|
```
|
||||||
|
|
||||||
|
Launch VM 2 (on the host machine) with an extra virtio-blk device for
|
||||||
|
exposing the same guest image for the nested destination VM:
|
||||||
|
```bash
|
||||||
|
$ sudo /target/release/cloud-hypervisor \
|
||||||
|
--serial tty --console off \
|
||||||
|
--cpus boot=1 --memory size=512M \
|
||||||
|
--kernel vmlinux \
|
||||||
|
--cmdline "root=/dev/vda1 console=ttyS0" \
|
||||||
|
--disk path=focal-2.raw path=focal-nested.raw path=tmp.img\
|
||||||
|
--net ip=192.168.102.1
|
||||||
|
```
|
||||||
|
|
||||||
|
Launch the nested source VM (inside the guest OS of the VM 1) :
|
||||||
|
```bash
|
||||||
|
vm-1:~$ sudo ./cloud-hypervisor \
|
||||||
|
--serial tty --console off \
|
||||||
|
--memory size=128M \
|
||||||
|
--kernel vmlinux \
|
||||||
|
--cmdline "console=ttyS0 root=/dev/vda1" \
|
||||||
|
--disk path=/dev/vdb path=/dev/vdc \
|
||||||
|
--api-socket=/tmp/api1 \
|
||||||
|
--net ip=192.168.100.1
|
||||||
|
vm-1:~$ # setup the guest network if needed
|
||||||
|
vm-1:~$ sudo ip addr add 192.168.101.2/24 dev ens4
|
||||||
|
vm-1:~$ sudo ip link set up dev ens4
|
||||||
|
vm-1:~$ sudo ip r add default via 192.168.101.1
|
||||||
|
```
|
||||||
|
Optional: Run the guest workload below (on the guest OS of the nested source VM),
|
||||||
|
which performs intensive virtio-blk operations. Now the console of the nested
|
||||||
|
source VM should repeatedly print `"equal"`, and our goal is migrating
|
||||||
|
this VM and the running workload without interruption.
|
||||||
|
```bash
|
||||||
|
#/bin/bash
|
||||||
|
|
||||||
|
# On the guest OS of the nested source VM
|
||||||
|
|
||||||
|
input="/dev/vdb"
|
||||||
|
result=$(md5sum $input)
|
||||||
|
tmp=$(md5sum $input)
|
||||||
|
|
||||||
|
while [[ "$result" == "$tmp" ]]
|
||||||
|
do
|
||||||
|
echo "equal"
|
||||||
|
tmp=$(md5sum $input)
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "not equal"
|
||||||
|
echo "result = $result"
|
||||||
|
echo "tmp = $tmp"
|
||||||
|
```
|
||||||
|
|
||||||
|
Launch the nested destination VM (inside the guest OS of the VM 2):
|
||||||
|
```bash
|
||||||
|
vm-2:~$ sudo ./cloud-hypervisor --api-socket=/tmp/api2
|
||||||
|
vm-2:~$ # setup the guest network with the following commands if needed
|
||||||
|
vm-2:~$ sudo ip addr add 192.168.102.2/24 dev ens4
|
||||||
|
vm-2:~$ sudo ip link set up dev ens4
|
||||||
|
vm-2:~$ sudo ip r add default via 192.168.102.1
|
||||||
|
vm-2:~$ ping 192.168.101.2 # This should succeed
|
||||||
|
```
|
||||||
|
> Note: If the above ping failed, please check the iptables rule on the
|
||||||
|
> host machine, e.g. whether the policy for the `FORWARD` chain is set
|
||||||
|
> to `DROP` (which is the default setting configured by Docker).
|
||||||
|
|
||||||
|
Get ready for receiving migration for the nested destination VM (inside
|
||||||
|
the guest OS of the VM 2):
|
||||||
|
```bash
|
||||||
|
vm-2:~$ sudo ./ch-remote --api-socket=/tmp/api2 receive-migration unix:/tmp/sock2
|
||||||
|
vm-2:~$ sudo socat TCP-LISTEN:6000,reuseaddr UNIX-CLIENT:/tmp/sock2
|
||||||
|
```
|
||||||
|
|
||||||
|
Start to send migration for the nested source VM (inside the guest OS of
|
||||||
|
the VM 1):
|
||||||
|
```bash
|
||||||
|
vm-1:~$ sudo socat UNIX-LISTEN:/tmp/sock1,reuseaddr TCP:192.168.102.2:6000
|
||||||
|
vm-1:~$ sudo ./ch-remote --api-socket=/tmp/api1 send-migration unix:/tmp/sock1
|
||||||
|
```
|
||||||
|
|
||||||
|
When the above commands completed, the source VM should be successfully
|
||||||
|
migrated to the destination VM without interrupting our testing guest
|
||||||
|
workload. Now the destination VM is running the testing guest workload
|
||||||
|
while the source VM is paused.
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Using MACVTAP to Bridge onto Host Network
|
# Using MACVTAP to Bridge onto Host Network
|
||||||
|
|
||||||
Cloud Hypervisor supports using a MACVTAP device which is derived from a MACVLAN. Full details of configuring MACVLAN or MACVTAP is out of scope of this document. However the example below indicates how to bridge the guest directly onto the the network the host is on. Due to the lack of hairpin mode it not usually possible to reach the guest directly from the host.
|
Cloud Hypervisor supports using a MACVTAP device which is derived from a MACVLAN. Full details of configuring MACVLAN or MACVTAP is out of scope of this document. However the example below indicates how to bridge the guest directly onto the network the host is on. Due to the lack of hairpin mode it not usually possible to reach the guest directly from the host.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# The MAC address must be attached to the macvtap and be used inside the guest
|
# The MAC address must be attached to the macvtap and be used inside the guest
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Profiling
|
# Profiling
|
||||||
|
|
||||||
`perf` can be used to profile the `cloud-hypervisor` binary but it is necessary to make some modifications to the the build in order to produce a binary that gives useful results.
|
`perf` can be used to profile the `cloud-hypervisor` binary but it is necessary to make some modifications to the build in order to produce a binary that gives useful results.
|
||||||
|
|
||||||
## Building a suitable binary
|
## Building a suitable binary
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ by the VFIO kernel drivers. However, by default, a host device will be bound to
|
|||||||
its native driver, which is not the VFIO one.
|
its native driver, which is not the VFIO one.
|
||||||
|
|
||||||
As a consequence, a device must be unbound from its native driver before passing
|
As a consequence, a device must be unbound from its native driver before passing
|
||||||
it to `cloud-hypervisor` for assigning it to a guess.
|
it to `cloud-hypervisor` for assigning it to a guest.
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
|
|||||||
@@ -35,38 +35,52 @@ Here are some good references for detailing them.
|
|||||||
|
|
||||||
## Test environment
|
## Test environment
|
||||||
|
|
||||||
The below test environment is based on ubuntu release(16.04.1 LTS), as for other system, please check related document.
|
The below test environment is based on Ubuntu release (20.04.1 LTS), as for other system, please check related documents.
|
||||||
The test runs with multiple queue (MQ) support enabled, using 4 queues defined for both SPDK and the virtual machine.
|
This test runs with multiple queue (MQ) support enabled, using 4 queues defined for both SPDK and the virtual machine.
|
||||||
Here are the details on how the test can be run.
|
Here are the detailed instructions.
|
||||||
|
|
||||||
### The hugepages settings in host linux
|
### The hugepages settings on the host
|
||||||
Add "default_hugepagesz=1G hugepagesz=1G hugepages=2" into host linux cmdline.
|
Allocate enough persistent huge pages (e.g. 2GiB) on the host:
|
||||||
As for how to change Ubuntu linux cmdline in grub file, please ref below link:
|
|
||||||
https://www.ostechnix.com/configure-grub-2-boot-loader-settings-ubuntu-16-04/
|
```bash
|
||||||
reboot Ubuntu
|
# Assume the default hugepage size is 2MiB
|
||||||
sudo mount -t hugetlbfs -o pagesize=1G none /dev/hugepages
|
echo 1024 | sudo tee /proc/sys/vm/nr_hugepages
|
||||||
|
# Confirm the value of "Hugepagesize" and "HugePages_Total"
|
||||||
|
cat /proc/meminfo | grep -i huge
|
||||||
|
```
|
||||||
|
|
||||||
### Download the SPDK code
|
### Download the SPDK code
|
||||||
|
```bash
|
||||||
git clone https://github.com/spdk/spdk
|
git clone https://github.com/spdk/spdk
|
||||||
cd spdk
|
cd spdk
|
||||||
git submodule update --init
|
git submodule update --init
|
||||||
|
```
|
||||||
|
|
||||||
### Create the build dep
|
### Create the build dep
|
||||||
./scripts/pkgdep.sh
|
|
||||||
|
|
||||||
### Build spdk
|
```bash
|
||||||
|
./scripts/pkgdep.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build SPDK
|
||||||
|
```bash
|
||||||
./configure
|
./configure
|
||||||
make
|
make
|
||||||
|
```
|
||||||
|
|
||||||
### Set the SPDk environment
|
### Set the SPDK environment
|
||||||
|
```bash
|
||||||
sudo HUGEMEM=2048 scripts/setup.sh
|
sudo HUGEMEM=2048 scripts/setup.sh
|
||||||
sudo ./app/vhost/vhost -S /var/tmp -s 1024 -m 0x3 &
|
sudo ./build/bin/vhost -S /var/tmp -s 1024 -m 0x3 &
|
||||||
|
```
|
||||||
|
|
||||||
### Create 512M block device
|
### Create 512M block device
|
||||||
|
```bash
|
||||||
sudo scripts/rpc.py bdev_malloc_create 512 512 -b Malloc0
|
sudo scripts/rpc.py bdev_malloc_create 512 512 -b Malloc0
|
||||||
sudo scripts/rpc.py vhost_create_blk_controller --cpumask 0x1 vhost.1 Malloc0
|
sudo scripts/rpc.py vhost_create_blk_controller --cpumask 0x1 vhost.1 Malloc0
|
||||||
|
```
|
||||||
|
|
||||||
_Launch the VM_
|
### Launch the VM
|
||||||
|
|
||||||
VMs run in client mode. They connect to the socket created by the `dpdkvhostuser` in the SPDK backend.
|
VMs run in client mode. They connect to the socket created by the `dpdkvhostuser` in the SPDK backend.
|
||||||
```bash
|
```bash
|
||||||
@@ -89,9 +103,9 @@ login in guest
|
|||||||
# Use lsblk command to find out vhost-user-blk device
|
# Use lsblk command to find out vhost-user-blk device
|
||||||
lsblk
|
lsblk
|
||||||
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
|
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
|
||||||
vda 252:0 0 2.2G 0 disk
|
vda 252:0 0 2.2G 0 disk
|
||||||
├─vda1 252:1 0 2.1G 0 part /
|
├─vda1 252:1 0 2.1G 0 part /
|
||||||
├─vda14 252:14 0 4M 0 part
|
├─vda14 252:14 0 4M 0 part
|
||||||
└─vda15 252:15 0 106M 0 part /boot/efi
|
└─vda15 252:15 0 106M 0 part /boot/efi
|
||||||
vdb 253:16 0 512M 0 disk
|
vdb 253:16 0 512M 0 disk
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,30 @@
|
|||||||
# How to test Vhost-user net with OpenVSwitch/DPDK
|
# How to test Vhost-user net with OpenVSwitch/DPDK
|
||||||
|
|
||||||
The purpose of this document is to illustrate how to test vhost-user-net in cloud-hypervisor with OVS/DPDK as the backend.
|
The purpose of this document is to illustrate how to test vhost-user-net
|
||||||
|
in cloud-hypervisor with OVS/DPDK as the backend. This document was
|
||||||
|
tested with Open vSwitch v2.13.1, DPDK v19.11.3, and Cloud Hypervisor
|
||||||
|
v15.0 on Ubuntu 20.04.1 (host kernel v5.4.0).
|
||||||
|
|
||||||
## Framework
|
## Framework
|
||||||
|
|
||||||
It's a simple test to validate the communication between two virtual machine, connecting them to vhost-user ports respectively provided by `OVS/DPDK`.
|
It's a simple test to validate the communication between two virtual machine, connecting them to vhost-user ports respectively provided by `OVS/DPDK`.
|
||||||
```
|
```
|
||||||
+----+----------+ +-------------+-----------+-------------+ +----------+----+
|
+----+----------+ +-------------+-----------+-------------+ +----------+----+
|
||||||
| | | | | | | | | |
|
| | | | | | | | | |
|
||||||
| |vhost-user|----------| vhost-user | ovs | vhost-user |----------|vhost-user| |
|
| |vhost-user|----------| vhost-user | ovs | vhost-user |----------|vhost-user| |
|
||||||
| |net device| | port 1 | | port 2 | |net device| |
|
| |net device| | port 1 | | port 2 | |net device| |
|
||||||
| | | | | | | | | |
|
| | | | | | | | | |
|
||||||
| +----------+ +-------------+-----------+-------------+ +----------+ |
|
| +----------+ +-------------+-----------+-------------+ +----------+ |
|
||||||
| | | | | |
|
| | | | | |
|
||||||
|vm1 | | dpdk | | vm2 |
|
|vm1 | | dpdk | | vm2 |
|
||||||
| | | | | |
|
| | | | | |
|
||||||
+--+---------------------------------------------------------------------------------------------+--+
|
+--+---------------------------------------------------------------------------------------------+--+
|
||||||
| | hugepages | |
|
| | hugepages | |
|
||||||
| +---------------------------------------------------------------------------------------------+ |
|
| +---------------------------------------------------------------------------------------------+ |
|
||||||
| |
|
| |
|
||||||
| host |
|
| host |
|
||||||
| |
|
| |
|
||||||
+---------------------------------------------------------------------------------------------------+
|
+---------------------------------------------------------------------------------------------------+
|
||||||
```
|
```
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
@@ -30,44 +33,54 @@ Prior to running the test, the following steps need to be performed.
|
|||||||
- Install DPDK
|
- Install DPDK
|
||||||
- Install OVS
|
- Install OVS
|
||||||
|
|
||||||
Here are some good references for detailing them.
|
Here is a good reference for setting up OVS with DPDK from scratch:
|
||||||
- Red Hat
|
https://docs.openvswitch.org/en/latest/intro/install/dpdk/.
|
||||||
* https://wiki.qemu.org/Documentation/vhost-user-ovs-dpdk
|
|
||||||
- Ubuntu server
|
|
||||||
* https://help.ubuntu.com/lts/serverguide/DPDK.html
|
|
||||||
* https://software.intel.com/en-us/articles/set-up-open-vswitch-with-dpdk-on-ubuntu-server
|
|
||||||
|
|
||||||
|
On Ubuntu systems (18.04 or newer), the OpenVswitch-DPDK package can be
|
||||||
|
easily installed with:
|
||||||
|
```bash
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install openvswitch-switch-dpdk
|
||||||
|
sudo update-alternatives --set ovs-vswitchd /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk
|
||||||
|
```
|
||||||
## Test
|
## Test
|
||||||
The test runs with multiple queue (MQ) support enabled, using 2 pairs of TX/RX queues defined for both OVS and the virtual machine. Here are the details on how the test can be run.
|
The test runs with multiple queue (MQ) support enabled, using 2 pairs of
|
||||||
|
TX/RX queues defined for both OVS and the virtual machine. Here are the
|
||||||
|
detailed instructions.
|
||||||
|
|
||||||
_Setup OVS_
|
_Setup OVS_
|
||||||
|
|
||||||
`ovs_test.sh` is created to setup and start OVS. OVS will provide the `dpdkvhostuser` backend running in server mode.
|
Here is an example how to configure a basic OpenVswitch using DPDK:
|
||||||
```bash
|
```bash
|
||||||
mkdir -p /var/run/openvswitch
|
# load the ovs kernel module
|
||||||
modprobe openvswitch
|
modprobe openvswitch
|
||||||
killall ovsdb-server ovs-vswitchd
|
sudo service openvswitch-switch start
|
||||||
rm -f /var/run/openvswitch/vhost-user*
|
ovs-vsctl init
|
||||||
rm -f /etc/openvswitch/conf.db
|
ovs-vsctl set Open_vSwitch . other_config:dpdk-init=true
|
||||||
export DB_SOCK=/var/run/openvswitch/db.sock
|
# run on core 0-3 only
|
||||||
ovsdb-tool create /etc/openvswitch/conf.db /usr/share/openvswitch/vswitch.ovsschema
|
ovs-vsctl set Open_vSwitch . other_config:dpdk-lcore-mask=0xf
|
||||||
ovsdb-server --remote=punix:$DB_SOCK --remote=db:Open_vSwitch,Open_vSwitch,manager_options --pidfile --detach
|
# allocate 2G huge pages (to NUMA 0 only)
|
||||||
ovs-vsctl --no-wait init
|
ovs-vsctl set Open_vSwitch . other_config:dpdk-socket-mem=1024
|
||||||
ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-lcore-mask=0xf
|
# run PMD (Pull Mode Driver) threads on core 0-3 only
|
||||||
ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-socket-mem=1024
|
ovs-vsctl set Open_vSwitch . other_config:pmd-cpu-mask=0xf
|
||||||
ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true
|
sudo service openvswitch-switch restart
|
||||||
ovs-vsctl --no-wait set Open_vSwitch . other_config:pmd-cpu-mask=0xf
|
# double check the configurations
|
||||||
ovs-vswitchd unix:$DB_SOCK --pidfile --detach --log-file=/var/log/openvswitch/ovs-vswitchd.log
|
ovs-vsctl list Open_vSwitch
|
||||||
|
```
|
||||||
|
|
||||||
|
Here is an example how to create a bridge and add two DPDK ports to it
|
||||||
|
(for later use via Cloud Hypervisor):
|
||||||
|
```bash
|
||||||
|
# create a bridge
|
||||||
ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev
|
ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev
|
||||||
|
# create two DPDK ports and add them to the bridge
|
||||||
ovs-vsctl add-port ovsbr0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser
|
ovs-vsctl add-port ovsbr0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser
|
||||||
ovs-vsctl add-port ovsbr0 vhost-user2 -- set Interface vhost-user2 type=dpdkvhostuser
|
ovs-vsctl add-port ovsbr0 vhost-user2 -- set Interface vhost-user2
|
||||||
|
type=dpdkvhostuser
|
||||||
|
# set the number of rx queues
|
||||||
ovs-vsctl set Interface vhost-user1 options:n_rxq=2
|
ovs-vsctl set Interface vhost-user1 options:n_rxq=2
|
||||||
ovs-vsctl set Interface vhost-user2 options:n_rxq=2
|
ovs-vsctl set Interface vhost-user2 options:n_rxq=2
|
||||||
```
|
```
|
||||||
_Run ovs_test.sh_
|
|
||||||
```bash
|
|
||||||
./ovs_test.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
_Launch the VMs_
|
_Launch the VMs_
|
||||||
|
|
||||||
@@ -89,19 +102,21 @@ VMs run in client mode. They connect to the socket created by the `dpdkvhostuser
|
|||||||
--kernel vmlinux \
|
--kernel vmlinux \
|
||||||
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
|
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
|
||||||
--disk path=focal-server-cloudimg-amd64.raw \
|
--disk path=focal-server-cloudimg-amd64.raw \
|
||||||
--net "mac=52:54:20:11:C5:02,vhost_user=true,socket=/var/run/openvswitch/vhost-user2,num_queues=4"
|
--net mac=52:54:20:11:C5:02,vhost_user=true,socket=/var/run/openvswitch/vhost-user2,num_queues=4
|
||||||
```
|
```
|
||||||
|
|
||||||
_Setup VM1_
|
_Setup VM1_
|
||||||
```bash
|
```bash
|
||||||
# From inside the guest
|
# From inside the guest
|
||||||
sudo ip addr add 172.100.0.1/24 dev enp0s3
|
sudo ip addr add 172.100.0.1/24 dev ens2
|
||||||
|
sudo ip link set up dev ens2
|
||||||
```
|
```
|
||||||
|
|
||||||
_Setup VM2_
|
_Setup VM2_
|
||||||
```bash
|
```bash
|
||||||
# From inside the guest
|
# From inside the guest
|
||||||
sudo ip addr add 172.100.0.2/24 dev enp0s3
|
sudo ip addr add 172.100.0.2/24 dev ens2
|
||||||
|
sudo ip link set up dev ens2
|
||||||
```
|
```
|
||||||
|
|
||||||
_Ping VM1 from VM2_
|
_Ping VM1 from VM2_
|
||||||
@@ -129,4 +144,3 @@ _Run VM2 as client_
|
|||||||
# From inside the guest
|
# From inside the guest
|
||||||
iperf3 -c 172.100.0.1 -t 30 -p 4444 &
|
iperf3 -c 172.100.0.1 -t 30 -p 4444 &
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -192,6 +192,8 @@ RAM hotplug is supported. Note, that while the `pnpmem.sys` driver in use suppor
|
|||||||
|
|
||||||
Network device hotplug and hot-remove are supported.
|
Network device hotplug and hot-remove are supported.
|
||||||
|
|
||||||
|
Disk hotplug and hot-remove are supported. After the device has been hotplugged, it will need to be onlined from within the guest. Among other tools, powershell applets `Get-Disk` and `Set-Disk` can be used for the disk configuration and activation.
|
||||||
|
|
||||||
## Debugging
|
## Debugging
|
||||||
|
|
||||||
The Windows guest debugging process relies heavily on QEMU and [socat](http://www.dest-unreach.org/socat/). The procedure requires two Windows VMs:
|
The Windows guest debugging process relies heavily on QEMU and [socat](http://www.dest-unreach.org/socat/). The procedure requires two Windows VMs:
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ authors = ["The Cloud Hypervisor Authors"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2.94"
|
libc = "0.2.96"
|
||||||
serde = {version = ">=1.0.27", features = ["rc"] }
|
serde = {version = ">=1.0.27", features = ["rc"] }
|
||||||
serde_derive = ">=1.0.27"
|
serde_derive = ">=1.0.27"
|
||||||
serde_json = ">=1.0.9"
|
serde_json = ">=1.0.9"
|
||||||
|
|||||||
174
fuzz/Cargo.lock
generated
174
fuzz/Cargo.lock
generated
@@ -30,15 +30,15 @@ version = "0.1.0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arbitrary"
|
name = "arbitrary"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "698b65a961a9d730fb45b6b0327e20207810c9f61ee421b082b27ba003f49e2b"
|
checksum = "237430fd6ed3740afe94eefcc278ae21e050285be882804e0d6e8695f0c94691"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arc-swap"
|
name = "arc-swap"
|
||||||
version = "1.2.0"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4d7d63395147b81a9e570bcc6243aaf71c017bd666d4909cfef0085bdda8d73"
|
checksum = "e906254e445520903e7fc9da4f709886c84ae4bc4ddaf0e093188d66df4dc820"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arch"
|
name = "arch"
|
||||||
@@ -46,24 +46,20 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"acpi_tables",
|
"acpi_tables",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"arch_gen",
|
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"hypervisor",
|
"hypervisor",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-loader",
|
"linux-loader",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"versionize",
|
||||||
|
"versionize_derive",
|
||||||
|
"vm-fdt",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vm-migration",
|
"vm-migration",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "arch_gen"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
@@ -75,6 +71,15 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bincode"
|
||||||
|
version = "1.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
@@ -89,10 +94,9 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"qcow",
|
"qcow",
|
||||||
"serde",
|
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"versionize",
|
||||||
|
"versionize_derive",
|
||||||
"virtio-bindings",
|
"virtio-bindings",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vm-virtio",
|
"vm-virtio",
|
||||||
@@ -107,9 +111,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.67"
|
version = "1.0.68"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
|
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@@ -135,7 +139,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cloud-hypervisor"
|
name = "cloud-hypervisor"
|
||||||
version = "0.14.0"
|
version = "15.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"api_client",
|
"api_client",
|
||||||
@@ -171,20 +175,26 @@ dependencies = [
|
|||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc64"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55626594feae15d266d52440b26ff77de0e22230cf0c113abe619084c1ddc910"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "devices"
|
name = "devices"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"acpi_tables",
|
"acpi_tables",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"arch",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"epoll",
|
"epoll",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"versionize",
|
||||||
"serde_derive",
|
"versionize_derive",
|
||||||
"serde_json",
|
|
||||||
"vm-device",
|
"vm-device",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vm-migration",
|
"vm-migration",
|
||||||
@@ -241,9 +251,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced-x86"
|
name = "iced-x86"
|
||||||
version = "1.11.1"
|
version = "1.11.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97b85a147f5dcb22ece887da5b99187954cc046939f22416e953dd7c336e85a1"
|
checksum = "6d907dfc273d9ed0da940e8145ceb77759056a1fb2110b44b83d1b203cddb906"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
@@ -277,9 +287,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kvm-ioctls"
|
name = "kvm-ioctls"
|
||||||
version = "0.8.0"
|
version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "74058b16912c6723db02d4ca3ec919b73cd41512ccd3b6202cf91ae8d6c9dce5"
|
checksum = "f2924454e22895c738e43331ae310459c74a11ded9c97dc250129ee10d2f9ca2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kvm-bindings",
|
"kvm-bindings",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -294,18 +304,19 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.94"
|
version = "0.2.96"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
|
checksum = "5600b4e6efc5421841a2138a6b082e07fe12f9aaa12783d50e5d13325b26b4fc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libfuzzer-sys"
|
name = "libfuzzer-sys"
|
||||||
version = "0.4.0"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86c975d637bc2a2f99440932b731491fc34c7f785d239e38af3addd3c2fd0e46"
|
checksum = "36a9a84a6e8b55dfefb04235e55edb2b9a2a18488fcae777a6bdaa6f06f1deb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arbitrary",
|
"arbitrary",
|
||||||
"cc",
|
"cc",
|
||||||
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -352,12 +363,20 @@ dependencies = [
|
|||||||
"net_gen",
|
"net_gen",
|
||||||
"rate_limiter",
|
"rate_limiter",
|
||||||
"serde",
|
"serde",
|
||||||
|
"versionize",
|
||||||
|
"versionize_derive",
|
||||||
"virtio-bindings",
|
"virtio-bindings",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vm-virtio",
|
"vm-virtio",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "option_parser"
|
name = "option_parser"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -371,9 +390,8 @@ dependencies = [
|
|||||||
"hypervisor",
|
"hypervisor",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"versionize",
|
||||||
"serde_derive",
|
"versionize_derive",
|
||||||
"serde_json",
|
|
||||||
"vfio-bindings",
|
"vfio-bindings",
|
||||||
"vfio-ioctls",
|
"vfio-ioctls",
|
||||||
"vm-allocator",
|
"vm-allocator",
|
||||||
@@ -385,9 +403,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.26"
|
version = "1.0.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
|
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
@@ -441,22 +459,22 @@ checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "seccomp"
|
name = "seccomp"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/firecracker-microvm/firecracker?tag=v0.24.2#5ba819d7b7a684107f5434bcbd1617bc94565478"
|
source = "git+https://github.com/firecracker-microvm/firecracker?tag=v0.24.4#8f44986a0e956a77f2b2324c12f73bec16130c82"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.125"
|
version = "1.0.126"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
|
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.125"
|
version = "1.0.126"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
|
checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -476,9 +494,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook"
|
name = "signal-hook"
|
||||||
version = "0.3.8"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ef33d6d0cd06e0840fba9985aab098c147e67e05cee14d412d3345ed14ff30ac"
|
checksum = "470c5a6397076fae0094aaf06a08e6ba6f37acb77d3b1b91ea92b4d6c8650c39"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
@@ -486,9 +504,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.3.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6"
|
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@@ -507,9 +525,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.71"
|
version = "1.0.73"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ad184cc9470f9117b2ac6817bfe297307418819ba40552f9b3846f05c33d5373"
|
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -538,18 +556,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.24"
|
version = "1.0.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
|
checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.24"
|
version = "1.0.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
|
checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -564,9 +582,15 @@ checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vec_map"
|
name = "vec_map"
|
||||||
@@ -574,6 +598,34 @@ version = "0.8.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "versionize"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7429cf68de8f091b667d27323ed323afd39584a56d533995b12ddd748e5e6ca9"
|
||||||
|
dependencies = [
|
||||||
|
"bincode",
|
||||||
|
"crc64",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"syn",
|
||||||
|
"versionize_derive",
|
||||||
|
"vmm-sys-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "versionize_derive"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "140aa9fd298f667ea50fa1cb0d8530076924079285c623b18b8f8a1c28386b4a"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vfio-bindings"
|
name = "vfio-bindings"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@@ -586,7 +638,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "vfio-ioctls"
|
name = "vfio-ioctls"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rust-vmm/vfio-ioctls?branch=master#a87b13bdec026e8144b91f30f35451a966d8c1ca"
|
source = "git+https://github.com/rust-vmm/vfio-ioctls?branch=master#5cb8550556620546e74b9fe6d1174e0d1fc83888"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"kvm-bindings",
|
"kvm-bindings",
|
||||||
@@ -600,7 +652,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "vhost"
|
name = "vhost"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rust-vmm/vhost?branch=master#ee3e8722706c984b3dfe12d3a130e92101b78e8f"
|
source = "git+https://github.com/rust-vmm/vhost?branch=master#e5b930b73a47cbdd79858e2e68bcb57123d1c1f3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -634,6 +686,8 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"versionize",
|
||||||
|
"versionize_derive",
|
||||||
"vhost",
|
"vhost",
|
||||||
"virtio-bindings",
|
"virtio-bindings",
|
||||||
"vm-allocator",
|
"vm-allocator",
|
||||||
@@ -667,11 +721,15 @@ dependencies = [
|
|||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vm-fdt"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/rust-vmm/vm-fdt?branch=master#13ab882e2f8387753064351c69fbe35c422b448b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vm-memory"
|
name = "vm-memory"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/rust-vmm/vm-memory?rev=5bd7138758183a73ac0da27ce40c004d95f1a7e9#5bd7138758183a73ac0da27ce40c004d95f1a7e9"
|
||||||
checksum = "625f401b1b8b3ac3d43f53903cd138cfe840bd985f8581e553027b31d2bb8ae8"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -687,6 +745,8 @@ dependencies = [
|
|||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"versionize",
|
||||||
|
"versionize_derive",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -695,9 +755,6 @@ name = "vm-virtio"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
|
||||||
"virtio-bindings",
|
"virtio-bindings",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
]
|
]
|
||||||
@@ -732,6 +789,9 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"uuid",
|
||||||
|
"versionize",
|
||||||
|
"versionize_derive",
|
||||||
"vfio-ioctls",
|
"vfio-ioctls",
|
||||||
"virtio-devices",
|
"virtio-devices",
|
||||||
"vm-allocator",
|
"vm-allocator",
|
||||||
|
|||||||
@@ -10,21 +10,22 @@ cargo-fuzz = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
block_util = { path = "../block_util" }
|
block_util = { path = "../block_util" }
|
||||||
libc = "0.2.94"
|
libc = "0.2.96"
|
||||||
libfuzzer-sys = "0.4"
|
libfuzzer-sys = "0.4.2"
|
||||||
qcow = { path = "../qcow" }
|
qcow = { path = "../qcow" }
|
||||||
seccomp = { git = "https://github.com/firecracker-microvm/firecracker", tag = "v0.24.2" }
|
seccomp = { git = "https://github.com/firecracker-microvm/firecracker", tag = "v0.24.4" }
|
||||||
virtio-devices = { path = "../virtio-devices" }
|
virtio-devices = { path = "../virtio-devices" }
|
||||||
vmm-sys-util = "0.8.0"
|
vmm-sys-util = "0.8.0"
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
vm-memory = "0.5.0"
|
vm-memory = "0.5.0"
|
||||||
|
|
||||||
[patch.crates-io]
|
|
||||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.4.0", features = ["with-serde", "fam-wrappers"] }
|
|
||||||
|
|
||||||
[dependencies.cloud-hypervisor]
|
[dependencies.cloud-hypervisor]
|
||||||
path = ".."
|
path = ".."
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.4.0", features = ["with-serde", "fam-wrappers"] }
|
||||||
|
vm-memory = { git = "https://github.com/rust-vmm/vm-memory", rev = "5bd7138758183a73ac0da27ce40c004d95f1a7e9"}
|
||||||
|
|
||||||
# Prevent this from interfering with workspaces
|
# Prevent this from interfering with workspaces
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["."]
|
members = ["."]
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ tdx = []
|
|||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
epoll = ">=4.0.1"
|
epoll = ">=4.0.1"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
libc = "0.2.94"
|
libc = "0.2.96"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
kvm-ioctls = { version = "0.8.0", optional = true }
|
kvm-ioctls = { version = "0.9.0", optional = true }
|
||||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.4.0", features = ["with-serde", "fam-wrappers"], optional = true }
|
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.4.0", features = ["with-serde", "fam-wrappers"], optional = true }
|
||||||
mshv-bindings = {git = "https://github.com/cloud-hypervisor/mshv", branch = "master", features = ["with-serde", "fam-wrappers"], optional = true }
|
mshv-bindings = {git = "https://github.com/cloud-hypervisor/mshv", branch = "master", features = ["with-serde", "fam-wrappers"], optional = true }
|
||||||
mshv-ioctls = { git = "https://github.com/cloud-hypervisor/mshv", branch = "master", optional = true}
|
mshv-ioctls = { git = "https://github.com/cloud-hypervisor/mshv", branch = "master", optional = true}
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
//
|
//
|
||||||
|
|
||||||
extern crate thiserror;
|
|
||||||
|
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
// CMP-Compare Two Operands
|
// CMP-Compare Two Operands
|
||||||
//
|
//
|
||||||
|
|
||||||
extern crate iced_x86;
|
|
||||||
|
|
||||||
use crate::arch::emulator::{EmulationError, PlatformEmulator};
|
use crate::arch::emulator::{EmulationError, PlatformEmulator};
|
||||||
use crate::arch::x86::emulator::instructions::*;
|
use crate::arch::x86::emulator::instructions::*;
|
||||||
use crate::arch::x86::regs::*;
|
use crate::arch::x86::regs::*;
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
//
|
//
|
||||||
|
|
||||||
extern crate iced_x86;
|
|
||||||
|
|
||||||
use crate::arch::emulator::{EmulationError, PlatformEmulator, PlatformError};
|
use crate::arch::emulator::{EmulationError, PlatformEmulator, PlatformError};
|
||||||
use crate::arch::x86::emulator::CpuStateManager;
|
use crate::arch::x86::emulator::CpuStateManager;
|
||||||
use crate::arch::x86::Exception;
|
use crate::arch::x86::Exception;
|
||||||
@@ -14,6 +12,7 @@ use iced_x86::*;
|
|||||||
pub mod cmp;
|
pub mod cmp;
|
||||||
pub mod mov;
|
pub mod mov;
|
||||||
pub mod movs;
|
pub mod movs;
|
||||||
|
pub mod or;
|
||||||
|
|
||||||
fn get_op<T: CpuStateManager>(
|
fn get_op<T: CpuStateManager>(
|
||||||
insn: &Instruction,
|
insn: &Instruction,
|
||||||
|
|||||||
@@ -12,8 +12,6 @@
|
|||||||
// Copies the second operand (source operand) to the first operand (destination operand).
|
// Copies the second operand (source operand) to the first operand (destination operand).
|
||||||
//
|
//
|
||||||
|
|
||||||
extern crate iced_x86;
|
|
||||||
|
|
||||||
use crate::arch::emulator::{EmulationError, PlatformEmulator};
|
use crate::arch::emulator::{EmulationError, PlatformEmulator};
|
||||||
use crate::arch::x86::emulator::instructions::*;
|
use crate::arch::x86::emulator::instructions::*;
|
||||||
use crate::arch::x86::Exception;
|
use crate::arch::x86::Exception;
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
// MOVS - Move Data from String to String
|
// MOVS - Move Data from String to String
|
||||||
//
|
//
|
||||||
|
|
||||||
extern crate iced_x86;
|
|
||||||
|
|
||||||
use crate::arch::emulator::{EmulationError, PlatformEmulator};
|
use crate::arch::emulator::{EmulationError, PlatformEmulator};
|
||||||
use crate::arch::x86::emulator::instructions::*;
|
use crate::arch::x86::emulator::instructions::*;
|
||||||
use crate::arch::x86::regs::DF;
|
use crate::arch::x86::regs::DF;
|
||||||
|
|||||||
83
hypervisor/src/arch/x86/emulator/instructions/or.rs
Normal file
83
hypervisor/src/arch/x86/emulator/instructions/or.rs
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
//
|
||||||
|
// Copyright © 2021 Microsoft
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
|
//
|
||||||
|
// OR - Logical inclusive OR
|
||||||
|
//
|
||||||
|
|
||||||
|
use crate::arch::emulator::{EmulationError, PlatformEmulator};
|
||||||
|
use crate::arch::x86::emulator::instructions::*;
|
||||||
|
use crate::arch::x86::Exception;
|
||||||
|
|
||||||
|
macro_rules! or_rm_r {
|
||||||
|
($bound:ty) => {
|
||||||
|
fn emulate(
|
||||||
|
&self,
|
||||||
|
insn: &Instruction,
|
||||||
|
state: &mut T,
|
||||||
|
platform: &mut dyn PlatformEmulator<CpuState = T>,
|
||||||
|
) -> Result<(), EmulationError<Exception>> {
|
||||||
|
let src_reg_value = get_op(&insn, 1, std::mem::size_of::<$bound>(), state, platform)
|
||||||
|
.map_err(EmulationError::PlatformEmulationError)?;
|
||||||
|
|
||||||
|
let dst_value = get_op(&insn, 0, std::mem::size_of::<$bound>(), state, platform)
|
||||||
|
.map_err(EmulationError::PlatformEmulationError)?;
|
||||||
|
|
||||||
|
let result = src_reg_value | dst_value;
|
||||||
|
|
||||||
|
set_op(
|
||||||
|
&insn,
|
||||||
|
0,
|
||||||
|
std::mem::size_of::<$bound>(),
|
||||||
|
state,
|
||||||
|
platform,
|
||||||
|
result,
|
||||||
|
)
|
||||||
|
.map_err(EmulationError::PlatformEmulationError)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Or_rm8_r8;
|
||||||
|
impl<T: CpuStateManager> InstructionHandler<T> for Or_rm8_r8 {
|
||||||
|
or_rm_r!(u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#![allow(unused_mut)]
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use crate::arch::x86::emulator::mock_vmm::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
// or byte ptr [rax+1h], sil
|
||||||
|
fn test_or_rm8_r8() {
|
||||||
|
let rax = 0;
|
||||||
|
let insn = [0x40, 0x08, 0x70, 0x1];
|
||||||
|
let cpu_id = 0;
|
||||||
|
let ip: u64 = 0x1000;
|
||||||
|
let sil = 0xaa;
|
||||||
|
let memory = [0x0, 0x55];
|
||||||
|
|
||||||
|
let mut vmm = MockVmm::new(
|
||||||
|
ip,
|
||||||
|
vec![(Register::SIL, sil), (Register::RAX, rax)],
|
||||||
|
Some((0, &memory)),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(vmm.emulate_first_insn(cpu_id, &insn).is_ok());
|
||||||
|
|
||||||
|
let mut out: [u8; 1] = [0; 1];
|
||||||
|
|
||||||
|
vmm.read_memory(rax + 1, &mut out).unwrap();
|
||||||
|
assert_eq!(u8::from_le_bytes(out), 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,8 +4,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
//
|
//
|
||||||
|
|
||||||
extern crate iced_x86;
|
|
||||||
|
|
||||||
use crate::arch::emulator::{EmulationError, EmulationResult, PlatformEmulator, PlatformError};
|
use crate::arch::emulator::{EmulationError, EmulationResult, PlatformEmulator, PlatformError};
|
||||||
use crate::arch::x86::emulator::instructions::*;
|
use crate::arch::x86::emulator::instructions::*;
|
||||||
use crate::arch::x86::regs::*;
|
use crate::arch::x86::regs::*;
|
||||||
@@ -526,7 +524,9 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> {
|
|||||||
(mov, Movzx_r32_rm16),
|
(mov, Movzx_r32_rm16),
|
||||||
(mov, Movzx_r64_rm16),
|
(mov, Movzx_r64_rm16),
|
||||||
// MOVS
|
// MOVS
|
||||||
(movs, Movsd_m32_m32)
|
(movs, Movsd_m32_m32),
|
||||||
|
// OR
|
||||||
|
(or, Or_rm8_r8)
|
||||||
);
|
);
|
||||||
|
|
||||||
handler
|
handler
|
||||||
@@ -640,8 +640,6 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> {
|
|||||||
mod mock_vmm {
|
mod mock_vmm {
|
||||||
#![allow(unused_mut)]
|
#![allow(unused_mut)]
|
||||||
|
|
||||||
extern crate env_logger;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::arch::emulator::{EmulationError, PlatformEmulator};
|
use crate::arch::emulator::{EmulationError, PlatformEmulator};
|
||||||
use crate::arch::x86::emulator::{Emulator, EmulatorCpuState as CpuState};
|
use crate::arch::x86::emulator::{Emulator, EmulatorCpuState as CpuState};
|
||||||
@@ -718,7 +716,7 @@ mod mock_vmm {
|
|||||||
"Memory read {} bytes from [{:#x} -> {:#x}]",
|
"Memory read {} bytes from [{:#x} -> {:#x}]",
|
||||||
data.len(),
|
data.len(),
|
||||||
gva,
|
gva,
|
||||||
gva
|
gva + data.len() as u64 - 1
|
||||||
);
|
);
|
||||||
data.copy_from_slice(&self.memory[gva as usize..gva as usize + data.len()]);
|
data.copy_from_slice(&self.memory[gva as usize..gva as usize + data.len()]);
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -729,7 +727,7 @@ mod mock_vmm {
|
|||||||
"Memory write {} bytes at [{:#x} -> {:#x}]",
|
"Memory write {} bytes at [{:#x} -> {:#x}]",
|
||||||
data.len(),
|
data.len(),
|
||||||
gva,
|
gva,
|
||||||
gva
|
gva + data.len() as u64 - 1
|
||||||
);
|
);
|
||||||
self.memory[gva as usize..gva as usize + data.len()].copy_from_slice(data);
|
self.memory[gva as usize..gva as usize + data.len()].copy_from_slice(data);
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ use crate::vm::Vm;
|
|||||||
use crate::x86_64::CpuId;
|
use crate::x86_64::CpuId;
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use crate::x86_64::MsrList;
|
use crate::x86_64::MsrList;
|
||||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
|
||||||
use kvm_ioctls::Cap;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
@@ -42,16 +40,6 @@ pub enum HypervisorError {
|
|||||||
#[error("Failed to get API Version: {0}")]
|
#[error("Failed to get API Version: {0}")]
|
||||||
GetApiVersion(#[source] anyhow::Error),
|
GetApiVersion(#[source] anyhow::Error),
|
||||||
///
|
///
|
||||||
/// Vcpu mmap error
|
|
||||||
///
|
|
||||||
#[error("Failed to get Vcpu Mmap: {0}")]
|
|
||||||
GetVcpuMmap(#[source] anyhow::Error),
|
|
||||||
///
|
|
||||||
/// Max Vcpu error
|
|
||||||
///
|
|
||||||
#[error("Failed to get number of max vcpus: {0}")]
|
|
||||||
GetMaxVcpu(#[source] anyhow::Error),
|
|
||||||
///
|
|
||||||
/// CpuId error
|
/// CpuId error
|
||||||
///
|
///
|
||||||
#[error("Failed to get cpuid: {0}")]
|
#[error("Failed to get cpuid: {0}")]
|
||||||
@@ -66,6 +54,11 @@ pub enum HypervisorError {
|
|||||||
///
|
///
|
||||||
#[error("Incompatible API version")]
|
#[error("Incompatible API version")]
|
||||||
IncompatibleApiVersion,
|
IncompatibleApiVersion,
|
||||||
|
///
|
||||||
|
/// Checking extensions failed
|
||||||
|
///
|
||||||
|
#[error("Checking extensions:{0}")]
|
||||||
|
CheckExtensions(#[source] anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -84,45 +77,32 @@ pub trait Hypervisor: Send + Sync {
|
|||||||
/// Return a hypervisor-agnostic Vm trait object
|
/// Return a hypervisor-agnostic Vm trait object
|
||||||
///
|
///
|
||||||
fn create_vm(&self) -> Result<Arc<dyn Vm>>;
|
fn create_vm(&self) -> Result<Arc<dyn Vm>>;
|
||||||
#[cfg(feature = "kvm")]
|
|
||||||
///
|
///
|
||||||
/// Create a Vm of a specific type using the underlying hypervisor
|
/// Create a Vm of a specific type using the underlying hypervisor
|
||||||
/// Return a hypervisor-agnostic Vm trait object
|
/// Return a hypervisor-agnostic Vm trait object
|
||||||
///
|
///
|
||||||
fn create_vm_with_type(&self, vm_type: u64) -> Result<Arc<dyn Vm>>;
|
fn create_vm_with_type(&self, _vm_type: u64) -> Result<Arc<dyn Vm>> {
|
||||||
#[cfg(feature = "kvm")]
|
unreachable!()
|
||||||
///
|
}
|
||||||
/// Returns the size of the memory mapping required to use the vcpu's structures
|
|
||||||
///
|
|
||||||
fn get_vcpu_mmap_size(&self) -> Result<usize>;
|
|
||||||
#[cfg(feature = "kvm")]
|
|
||||||
///
|
|
||||||
/// Gets the recommended maximum number of VCPUs per VM.
|
|
||||||
///
|
|
||||||
fn get_max_vcpus(&self) -> Result<usize>;
|
|
||||||
#[cfg(feature = "kvm")]
|
|
||||||
///
|
|
||||||
/// Gets the recommended number of VCPUs per VM.
|
|
||||||
///
|
|
||||||
fn get_nr_vcpus(&self) -> Result<usize>;
|
|
||||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
|
||||||
///
|
|
||||||
/// Checks if a particular `Cap` is available.
|
|
||||||
///
|
|
||||||
fn check_capability(&self, c: Cap) -> bool;
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
///
|
///
|
||||||
/// Get the supported CpuID
|
/// Get the supported CpuID
|
||||||
///
|
///
|
||||||
fn get_cpuid(&self) -> Result<CpuId>;
|
fn get_cpuid(&self) -> Result<CpuId>;
|
||||||
#[cfg(not(feature = "mshv"))]
|
|
||||||
///
|
///
|
||||||
/// Check particular extensions if any
|
/// Check particular extensions if any
|
||||||
///
|
///
|
||||||
fn check_required_extensions(&self) -> Result<()>;
|
fn check_required_extensions(&self) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
///
|
///
|
||||||
/// Retrieve the list of MSRs supported by the hypervisor.
|
/// Retrieve the list of MSRs supported by the hypervisor.
|
||||||
///
|
///
|
||||||
fn get_msr_list(&self) -> Result<MsrList>;
|
fn get_msr_list(&self) -> Result<MsrList>;
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
///
|
||||||
|
/// Retrieve AArch64 host maximum IPA size supported by KVM.
|
||||||
|
///
|
||||||
|
fn get_host_ipa_limit(&self) -> i32;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,19 +32,17 @@ pub use {kvm_ioctls::Cap, kvm_ioctls::Kvm};
|
|||||||
|
|
||||||
// This macro gets the offset of a structure (i.e `str`) member (i.e `field`) without having
|
// This macro gets the offset of a structure (i.e `str`) member (i.e `field`) without having
|
||||||
// an instance of that structure.
|
// an instance of that structure.
|
||||||
// It uses a null pointer to retrieve the offset to the field.
|
|
||||||
// Inspired by C solution: `#define offsetof(str, f) ((size_t)(&((str *)0)->f))`.
|
|
||||||
// Doing `offset__of!(user_pt_regs, pstate)` in our rust code will trigger the following:
|
|
||||||
// unsafe { &(*(0 as *const user_pt_regs)).pstate as *const _ as usize }
|
|
||||||
// The dereference expression produces an lvalue, but that lvalue is not actually read from,
|
|
||||||
// we're just doing pointer math on it, so in theory, it should safe.
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! offset__of {
|
macro_rules! offset__of {
|
||||||
($str:ty, $field:ident) => {
|
($str:ty, $($field:ident)+) => ({
|
||||||
unsafe { &(*std::ptr::null::<$str>()).$field as *const _ as usize }
|
let tmp: std::mem::MaybeUninit<$str> = std::mem::MaybeUninit::uninit();
|
||||||
};
|
let tmp = unsafe { tmp.assume_init() };
|
||||||
}
|
let base = &tmp as *const _ as usize;
|
||||||
|
let member = &tmp.$($field)* as *const _ as usize;
|
||||||
|
|
||||||
|
member - base
|
||||||
|
});
|
||||||
|
}
|
||||||
// Get the ID of a core register
|
// Get the ID of a core register
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! arm64_core_reg_id {
|
macro_rules! arm64_core_reg_id {
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ use crate::vm::{self, VmmOps};
|
|||||||
use crate::{arm64_core_reg_id, offset__of};
|
use crate::{arm64_core_reg_id, offset__of};
|
||||||
use kvm_ioctls::{NoDatamatch, VcpuFd, VmFd};
|
use kvm_ioctls::{NoDatamatch, VcpuFd, VmFd};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
use std::convert::TryInto;
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
use std::result;
|
use std::result;
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
@@ -70,9 +72,9 @@ pub use kvm_ioctls;
|
|||||||
pub use kvm_ioctls::{Cap, Kvm};
|
pub use kvm_ioctls::{Cap, Kvm};
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use thiserror::Error;
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
use vmm_sys_util::{ioctl::ioctl_with_val, ioctl_expr, ioctl_ioc_nr, ioctl_iowr_nr};
|
use vmm_sys_util::{ioctl::ioctl_with_val, ioctl_expr, ioctl_ioc_nr, ioctl_iowr_nr};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Export generically-named wrappers of kvm-bindings for Unix-based platforms
|
/// Export generically-named wrappers of kvm-bindings for Unix-based platforms
|
||||||
///
|
///
|
||||||
@@ -373,7 +375,7 @@ impl vm::Vm for KvmVm {
|
|||||||
let data = TdxInitVm {
|
let data = TdxInitVm {
|
||||||
max_vcpus,
|
max_vcpus,
|
||||||
reserved: 0,
|
reserved: 0,
|
||||||
attributes: 0,
|
attributes: 1, // TDX1_TD_ATTRIBUTE_DEBUG,
|
||||||
cpuid: cpuid.as_fam_struct_ptr() as u64,
|
cpuid: cpuid.as_fam_struct_ptr() as u64,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -465,8 +467,9 @@ pub struct KvmHypervisor {
|
|||||||
kvm: Kvm,
|
kvm: Kvm,
|
||||||
}
|
}
|
||||||
/// Enum for KVM related error
|
/// Enum for KVM related error
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Error)]
|
||||||
pub enum KvmError {
|
pub enum KvmError {
|
||||||
|
#[error("Capability missing: {0:?}")]
|
||||||
CapabilityMissing(Cap),
|
CapabilityMissing(Cap),
|
||||||
}
|
}
|
||||||
pub type KvmResult<T> = result::Result<T, KvmError>;
|
pub type KvmResult<T> = result::Result<T, KvmError>;
|
||||||
@@ -557,41 +560,25 @@ impl hypervisor::Hypervisor for KvmHypervisor {
|
|||||||
/// let vm = hypervisor.create_vm().unwrap()
|
/// let vm = hypervisor.create_vm().unwrap()
|
||||||
///
|
///
|
||||||
fn create_vm(&self) -> hypervisor::Result<Arc<dyn vm::Vm>> {
|
fn create_vm(&self) -> hypervisor::Result<Arc<dyn vm::Vm>> {
|
||||||
self.create_vm_with_type(0) // Create with default platform type
|
#[allow(unused_mut)]
|
||||||
|
let mut vm_type: u64 = 0; // Create with default platform type
|
||||||
|
|
||||||
|
// When KVM supports Cap::ArmVmIPASize, it is better to get the IPA
|
||||||
|
// size from the host and use that when creating the VM, which may
|
||||||
|
// avoid unnecessary VM creation failures.
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
if self.kvm.check_extension(Cap::ArmVmIPASize) {
|
||||||
|
vm_type = self.kvm.get_host_ipa_limit().try_into().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.create_vm_with_type(vm_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_required_extensions(&self) -> hypervisor::Result<()> {
|
fn check_required_extensions(&self) -> hypervisor::Result<()> {
|
||||||
check_required_kvm_extensions(&self.kvm).expect("Missing KVM capabilities");
|
check_required_kvm_extensions(&self.kvm)
|
||||||
Ok(())
|
.map_err(|e| hypervisor::HypervisorError::CheckExtensions(e.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// Returns the size of the memory mapping required to use the vcpu's `kvm_run` structure.
|
|
||||||
///
|
|
||||||
fn get_vcpu_mmap_size(&self) -> hypervisor::Result<usize> {
|
|
||||||
self.kvm
|
|
||||||
.get_vcpu_mmap_size()
|
|
||||||
.map_err(|e| hypervisor::HypervisorError::GetVcpuMmap(e.into()))
|
|
||||||
}
|
|
||||||
///
|
|
||||||
/// Gets the recommended maximum number of VCPUs per VM.
|
|
||||||
///
|
|
||||||
fn get_max_vcpus(&self) -> hypervisor::Result<usize> {
|
|
||||||
Ok(self.kvm.get_max_vcpus())
|
|
||||||
}
|
|
||||||
///
|
|
||||||
/// Gets the recommended number of VCPUs per VM.
|
|
||||||
///
|
|
||||||
fn get_nr_vcpus(&self) -> hypervisor::Result<usize> {
|
|
||||||
Ok(self.kvm.get_nr_vcpus())
|
|
||||||
}
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
///
|
|
||||||
/// Checks if a particular `Cap` is available.
|
|
||||||
///
|
|
||||||
fn check_capability(&self, c: Cap) -> bool {
|
|
||||||
self.kvm.check_extension(c)
|
|
||||||
}
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
///
|
///
|
||||||
/// X86 specific call to get the system supported CPUID values.
|
/// X86 specific call to get the system supported CPUID values.
|
||||||
@@ -601,6 +588,7 @@ impl hypervisor::Hypervisor for KvmHypervisor {
|
|||||||
.get_supported_cpuid(kvm_bindings::KVM_MAX_CPUID_ENTRIES)
|
.get_supported_cpuid(kvm_bindings::KVM_MAX_CPUID_ENTRIES)
|
||||||
.map_err(|e| hypervisor::HypervisorError::GetCpuId(e.into()))
|
.map_err(|e| hypervisor::HypervisorError::GetCpuId(e.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
///
|
///
|
||||||
/// Retrieve the list of MSRs supported by KVM.
|
/// Retrieve the list of MSRs supported by KVM.
|
||||||
@@ -610,6 +598,13 @@ impl hypervisor::Hypervisor for KvmHypervisor {
|
|||||||
.get_msr_index_list()
|
.get_msr_index_list()
|
||||||
.map_err(|e| hypervisor::HypervisorError::GetMsrList(e.into()))
|
.map_err(|e| hypervisor::HypervisorError::GetMsrList(e.into()))
|
||||||
}
|
}
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
///
|
||||||
|
/// Retrieve AArch64 host maximum IPA size supported by KVM.
|
||||||
|
///
|
||||||
|
fn get_host_ipa_limit(&self) -> i32 {
|
||||||
|
self.kvm.get_host_ipa_limit()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// Vcpu struct for KVM
|
/// Vcpu struct for KVM
|
||||||
pub struct KvmVcpu {
|
pub struct KvmVcpu {
|
||||||
|
|||||||
@@ -23,10 +23,6 @@ extern crate anyhow;
|
|||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
extern crate serde;
|
|
||||||
extern crate serde_derive;
|
|
||||||
extern crate serde_json;
|
|
||||||
extern crate thiserror;
|
|
||||||
|
|
||||||
/// Architecture specific definitions
|
/// Architecture specific definitions
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|||||||
@@ -473,7 +473,7 @@ impl cpu::Vcpu for MshvVcpu {
|
|||||||
///
|
///
|
||||||
fn set_xsave(&self, xsave: &Xsave) -> cpu::Result<()> {
|
fn set_xsave(&self, xsave: &Xsave) -> cpu::Result<()> {
|
||||||
self.fd
|
self.fd
|
||||||
.set_xsave(*xsave)
|
.set_xsave(xsave)
|
||||||
.map_err(|e| cpu::HypervisorCpuError::SetXsaveState(e.into()))
|
.map_err(|e| cpu::HypervisorCpuError::SetXsaveState(e.into()))
|
||||||
}
|
}
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
name = "net_gen"
|
name = "net_gen"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["The Chromium OS Authors"]
|
authors = ["The Chromium OS Authors"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
vmm-sys-util = ">=0.3.1"
|
vmm-sys-util = ">=0.3.1"
|
||||||
|
|||||||
@@ -1,24 +1,27 @@
|
|||||||
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
// Copyright © 2021 Intel Corporation
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
//
|
||||||
// found in the THIRD-PARTY file.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
/* automatically generated by rust-bindgen */
|
// bindgen /usr/include/linux/if_tun.h --no-layout-tests
|
||||||
|
|
||||||
|
/* automatically generated by rust-bindgen 0.58.1 */
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>);
|
pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>, [T; 0]);
|
||||||
impl<T> __IncompleteArrayField<T> {
|
impl<T> __IncompleteArrayField<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
__IncompleteArrayField(::std::marker::PhantomData)
|
__IncompleteArrayField(::std::marker::PhantomData, [])
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn as_ptr(&self) -> *const T {
|
pub fn as_ptr(&self) -> *const T {
|
||||||
::std::mem::transmute(self)
|
self as *const _ as *const T
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
|
pub fn as_mut_ptr(&mut self) -> *mut T {
|
||||||
::std::mem::transmute(self)
|
self as *mut _ as *mut T
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn as_slice(&self, len: usize) -> &[T] {
|
pub unsafe fn as_slice(&self, len: usize) -> &[T] {
|
||||||
@@ -30,191 +33,203 @@ impl<T> __IncompleteArrayField<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> {
|
impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> {
|
||||||
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||||
fmt.write_str("__IncompleteArrayField")
|
fmt.write_str("__IncompleteArrayField")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<T> ::std::clone::Clone for __IncompleteArrayField<T> {
|
pub const __BITS_PER_LONG: u32 = 64;
|
||||||
#[inline]
|
pub const __FD_SETSIZE: u32 = 1024;
|
||||||
fn clone(&self) -> Self {
|
pub const ETH_ALEN: u32 = 6;
|
||||||
Self::new()
|
pub const ETH_TLEN: u32 = 2;
|
||||||
}
|
pub const ETH_HLEN: u32 = 14;
|
||||||
}
|
pub const ETH_ZLEN: u32 = 60;
|
||||||
impl<T> ::std::marker::Copy for __IncompleteArrayField<T> {}
|
pub const ETH_DATA_LEN: u32 = 1500;
|
||||||
pub const __BITS_PER_LONG: ::std::os::raw::c_uint = 64;
|
pub const ETH_FRAME_LEN: u32 = 1514;
|
||||||
pub const __FD_SETSIZE: ::std::os::raw::c_uint = 1024;
|
pub const ETH_FCS_LEN: u32 = 4;
|
||||||
pub const ETH_ALEN: ::std::os::raw::c_uint = 6;
|
pub const ETH_MIN_MTU: u32 = 68;
|
||||||
pub const ETH_HLEN: ::std::os::raw::c_uint = 14;
|
pub const ETH_MAX_MTU: u32 = 65535;
|
||||||
pub const ETH_ZLEN: ::std::os::raw::c_uint = 60;
|
pub const ETH_P_LOOP: u32 = 96;
|
||||||
pub const ETH_DATA_LEN: ::std::os::raw::c_uint = 1500;
|
pub const ETH_P_PUP: u32 = 512;
|
||||||
pub const ETH_FRAME_LEN: ::std::os::raw::c_uint = 1514;
|
pub const ETH_P_PUPAT: u32 = 513;
|
||||||
pub const ETH_FCS_LEN: ::std::os::raw::c_uint = 4;
|
pub const ETH_P_TSN: u32 = 8944;
|
||||||
pub const ETH_P_LOOP: ::std::os::raw::c_uint = 96;
|
pub const ETH_P_ERSPAN2: u32 = 8939;
|
||||||
pub const ETH_P_PUP: ::std::os::raw::c_uint = 512;
|
pub const ETH_P_IP: u32 = 2048;
|
||||||
pub const ETH_P_PUPAT: ::std::os::raw::c_uint = 513;
|
pub const ETH_P_X25: u32 = 2053;
|
||||||
pub const ETH_P_TSN: ::std::os::raw::c_uint = 8944;
|
pub const ETH_P_ARP: u32 = 2054;
|
||||||
pub const ETH_P_IP: ::std::os::raw::c_uint = 2048;
|
pub const ETH_P_BPQ: u32 = 2303;
|
||||||
pub const ETH_P_X25: ::std::os::raw::c_uint = 2053;
|
pub const ETH_P_IEEEPUP: u32 = 2560;
|
||||||
pub const ETH_P_ARP: ::std::os::raw::c_uint = 2054;
|
pub const ETH_P_IEEEPUPAT: u32 = 2561;
|
||||||
pub const ETH_P_BPQ: ::std::os::raw::c_uint = 2303;
|
pub const ETH_P_BATMAN: u32 = 17157;
|
||||||
pub const ETH_P_IEEEPUP: ::std::os::raw::c_uint = 2560;
|
pub const ETH_P_DEC: u32 = 24576;
|
||||||
pub const ETH_P_IEEEPUPAT: ::std::os::raw::c_uint = 2561;
|
pub const ETH_P_DNA_DL: u32 = 24577;
|
||||||
pub const ETH_P_BATMAN: ::std::os::raw::c_uint = 17157;
|
pub const ETH_P_DNA_RC: u32 = 24578;
|
||||||
pub const ETH_P_DEC: ::std::os::raw::c_uint = 24576;
|
pub const ETH_P_DNA_RT: u32 = 24579;
|
||||||
pub const ETH_P_DNA_DL: ::std::os::raw::c_uint = 24577;
|
pub const ETH_P_LAT: u32 = 24580;
|
||||||
pub const ETH_P_DNA_RC: ::std::os::raw::c_uint = 24578;
|
pub const ETH_P_DIAG: u32 = 24581;
|
||||||
pub const ETH_P_DNA_RT: ::std::os::raw::c_uint = 24579;
|
pub const ETH_P_CUST: u32 = 24582;
|
||||||
pub const ETH_P_LAT: ::std::os::raw::c_uint = 24580;
|
pub const ETH_P_SCA: u32 = 24583;
|
||||||
pub const ETH_P_DIAG: ::std::os::raw::c_uint = 24581;
|
pub const ETH_P_TEB: u32 = 25944;
|
||||||
pub const ETH_P_CUST: ::std::os::raw::c_uint = 24582;
|
pub const ETH_P_RARP: u32 = 32821;
|
||||||
pub const ETH_P_SCA: ::std::os::raw::c_uint = 24583;
|
pub const ETH_P_ATALK: u32 = 32923;
|
||||||
pub const ETH_P_TEB: ::std::os::raw::c_uint = 25944;
|
pub const ETH_P_AARP: u32 = 33011;
|
||||||
pub const ETH_P_RARP: ::std::os::raw::c_uint = 32821;
|
pub const ETH_P_8021Q: u32 = 33024;
|
||||||
pub const ETH_P_ATALK: ::std::os::raw::c_uint = 32923;
|
pub const ETH_P_ERSPAN: u32 = 35006;
|
||||||
pub const ETH_P_AARP: ::std::os::raw::c_uint = 33011;
|
pub const ETH_P_IPX: u32 = 33079;
|
||||||
pub const ETH_P_8021Q: ::std::os::raw::c_uint = 33024;
|
pub const ETH_P_IPV6: u32 = 34525;
|
||||||
pub const ETH_P_IPX: ::std::os::raw::c_uint = 33079;
|
pub const ETH_P_PAUSE: u32 = 34824;
|
||||||
pub const ETH_P_IPV6: ::std::os::raw::c_uint = 34525;
|
pub const ETH_P_SLOW: u32 = 34825;
|
||||||
pub const ETH_P_PAUSE: ::std::os::raw::c_uint = 34824;
|
pub const ETH_P_WCCP: u32 = 34878;
|
||||||
pub const ETH_P_SLOW: ::std::os::raw::c_uint = 34825;
|
pub const ETH_P_MPLS_UC: u32 = 34887;
|
||||||
pub const ETH_P_WCCP: ::std::os::raw::c_uint = 34878;
|
pub const ETH_P_MPLS_MC: u32 = 34888;
|
||||||
pub const ETH_P_MPLS_UC: ::std::os::raw::c_uint = 34887;
|
pub const ETH_P_ATMMPOA: u32 = 34892;
|
||||||
pub const ETH_P_MPLS_MC: ::std::os::raw::c_uint = 34888;
|
pub const ETH_P_PPP_DISC: u32 = 34915;
|
||||||
pub const ETH_P_ATMMPOA: ::std::os::raw::c_uint = 34892;
|
pub const ETH_P_PPP_SES: u32 = 34916;
|
||||||
pub const ETH_P_PPP_DISC: ::std::os::raw::c_uint = 34915;
|
pub const ETH_P_LINK_CTL: u32 = 34924;
|
||||||
pub const ETH_P_PPP_SES: ::std::os::raw::c_uint = 34916;
|
pub const ETH_P_ATMFATE: u32 = 34948;
|
||||||
pub const ETH_P_LINK_CTL: ::std::os::raw::c_uint = 34924;
|
pub const ETH_P_PAE: u32 = 34958;
|
||||||
pub const ETH_P_ATMFATE: ::std::os::raw::c_uint = 34948;
|
pub const ETH_P_AOE: u32 = 34978;
|
||||||
pub const ETH_P_PAE: ::std::os::raw::c_uint = 34958;
|
pub const ETH_P_8021AD: u32 = 34984;
|
||||||
pub const ETH_P_AOE: ::std::os::raw::c_uint = 34978;
|
pub const ETH_P_802_EX1: u32 = 34997;
|
||||||
pub const ETH_P_8021AD: ::std::os::raw::c_uint = 34984;
|
pub const ETH_P_PREAUTH: u32 = 35015;
|
||||||
pub const ETH_P_802_EX1: ::std::os::raw::c_uint = 34997;
|
pub const ETH_P_TIPC: u32 = 35018;
|
||||||
pub const ETH_P_TIPC: ::std::os::raw::c_uint = 35018;
|
pub const ETH_P_LLDP: u32 = 35020;
|
||||||
pub const ETH_P_8021AH: ::std::os::raw::c_uint = 35047;
|
pub const ETH_P_MRP: u32 = 35043;
|
||||||
pub const ETH_P_MVRP: ::std::os::raw::c_uint = 35061;
|
pub const ETH_P_MACSEC: u32 = 35045;
|
||||||
pub const ETH_P_1588: ::std::os::raw::c_uint = 35063;
|
pub const ETH_P_8021AH: u32 = 35047;
|
||||||
pub const ETH_P_PRP: ::std::os::raw::c_uint = 35067;
|
pub const ETH_P_MVRP: u32 = 35061;
|
||||||
pub const ETH_P_FCOE: ::std::os::raw::c_uint = 35078;
|
pub const ETH_P_1588: u32 = 35063;
|
||||||
pub const ETH_P_TDLS: ::std::os::raw::c_uint = 35085;
|
pub const ETH_P_NCSI: u32 = 35064;
|
||||||
pub const ETH_P_FIP: ::std::os::raw::c_uint = 35092;
|
pub const ETH_P_PRP: u32 = 35067;
|
||||||
pub const ETH_P_80221: ::std::os::raw::c_uint = 35095;
|
pub const ETH_P_FCOE: u32 = 35078;
|
||||||
pub const ETH_P_LOOPBACK: ::std::os::raw::c_uint = 36864;
|
pub const ETH_P_IBOE: u32 = 35093;
|
||||||
pub const ETH_P_QINQ1: ::std::os::raw::c_uint = 37120;
|
pub const ETH_P_TDLS: u32 = 35085;
|
||||||
pub const ETH_P_QINQ2: ::std::os::raw::c_uint = 37376;
|
pub const ETH_P_FIP: u32 = 35092;
|
||||||
pub const ETH_P_QINQ3: ::std::os::raw::c_uint = 37632;
|
pub const ETH_P_80221: u32 = 35095;
|
||||||
pub const ETH_P_EDSA: ::std::os::raw::c_uint = 56026;
|
pub const ETH_P_HSR: u32 = 35119;
|
||||||
pub const ETH_P_AF_IUCV: ::std::os::raw::c_uint = 64507;
|
pub const ETH_P_NSH: u32 = 35151;
|
||||||
pub const ETH_P_802_3_MIN: ::std::os::raw::c_uint = 1536;
|
pub const ETH_P_LOOPBACK: u32 = 36864;
|
||||||
pub const ETH_P_802_3: ::std::os::raw::c_uint = 1;
|
pub const ETH_P_QINQ1: u32 = 37120;
|
||||||
pub const ETH_P_AX25: ::std::os::raw::c_uint = 2;
|
pub const ETH_P_QINQ2: u32 = 37376;
|
||||||
pub const ETH_P_ALL: ::std::os::raw::c_uint = 3;
|
pub const ETH_P_QINQ3: u32 = 37632;
|
||||||
pub const ETH_P_802_2: ::std::os::raw::c_uint = 4;
|
pub const ETH_P_EDSA: u32 = 56026;
|
||||||
pub const ETH_P_SNAP: ::std::os::raw::c_uint = 5;
|
pub const ETH_P_DSA_8021Q: u32 = 56027;
|
||||||
pub const ETH_P_DDCMP: ::std::os::raw::c_uint = 6;
|
pub const ETH_P_IFE: u32 = 60734;
|
||||||
pub const ETH_P_WAN_PPP: ::std::os::raw::c_uint = 7;
|
pub const ETH_P_AF_IUCV: u32 = 64507;
|
||||||
pub const ETH_P_PPP_MP: ::std::os::raw::c_uint = 8;
|
pub const ETH_P_802_3_MIN: u32 = 1536;
|
||||||
pub const ETH_P_LOCALTALK: ::std::os::raw::c_uint = 9;
|
pub const ETH_P_802_3: u32 = 1;
|
||||||
pub const ETH_P_CAN: ::std::os::raw::c_uint = 12;
|
pub const ETH_P_AX25: u32 = 2;
|
||||||
pub const ETH_P_CANFD: ::std::os::raw::c_uint = 13;
|
pub const ETH_P_ALL: u32 = 3;
|
||||||
pub const ETH_P_PPPTALK: ::std::os::raw::c_uint = 16;
|
pub const ETH_P_802_2: u32 = 4;
|
||||||
pub const ETH_P_TR_802_2: ::std::os::raw::c_uint = 17;
|
pub const ETH_P_SNAP: u32 = 5;
|
||||||
pub const ETH_P_MOBITEX: ::std::os::raw::c_uint = 21;
|
pub const ETH_P_DDCMP: u32 = 6;
|
||||||
pub const ETH_P_CONTROL: ::std::os::raw::c_uint = 22;
|
pub const ETH_P_WAN_PPP: u32 = 7;
|
||||||
pub const ETH_P_IRDA: ::std::os::raw::c_uint = 23;
|
pub const ETH_P_PPP_MP: u32 = 8;
|
||||||
pub const ETH_P_ECONET: ::std::os::raw::c_uint = 24;
|
pub const ETH_P_LOCALTALK: u32 = 9;
|
||||||
pub const ETH_P_HDLC: ::std::os::raw::c_uint = 25;
|
pub const ETH_P_CAN: u32 = 12;
|
||||||
pub const ETH_P_ARCNET: ::std::os::raw::c_uint = 26;
|
pub const ETH_P_CANFD: u32 = 13;
|
||||||
pub const ETH_P_DSA: ::std::os::raw::c_uint = 27;
|
pub const ETH_P_PPPTALK: u32 = 16;
|
||||||
pub const ETH_P_TRAILER: ::std::os::raw::c_uint = 28;
|
pub const ETH_P_TR_802_2: u32 = 17;
|
||||||
pub const ETH_P_PHONET: ::std::os::raw::c_uint = 245;
|
pub const ETH_P_MOBITEX: u32 = 21;
|
||||||
pub const ETH_P_IEEE802154: ::std::os::raw::c_uint = 246;
|
pub const ETH_P_CONTROL: u32 = 22;
|
||||||
pub const ETH_P_CAIF: ::std::os::raw::c_uint = 247;
|
pub const ETH_P_IRDA: u32 = 23;
|
||||||
pub const ETH_P_XDSA: ::std::os::raw::c_uint = 248;
|
pub const ETH_P_ECONET: u32 = 24;
|
||||||
pub const BPF_LD: ::std::os::raw::c_uint = 0;
|
pub const ETH_P_HDLC: u32 = 25;
|
||||||
pub const BPF_LDX: ::std::os::raw::c_uint = 1;
|
pub const ETH_P_ARCNET: u32 = 26;
|
||||||
pub const BPF_ST: ::std::os::raw::c_uint = 2;
|
pub const ETH_P_DSA: u32 = 27;
|
||||||
pub const BPF_STX: ::std::os::raw::c_uint = 3;
|
pub const ETH_P_TRAILER: u32 = 28;
|
||||||
pub const BPF_ALU: ::std::os::raw::c_uint = 4;
|
pub const ETH_P_PHONET: u32 = 245;
|
||||||
pub const BPF_JMP: ::std::os::raw::c_uint = 5;
|
pub const ETH_P_IEEE802154: u32 = 246;
|
||||||
pub const BPF_RET: ::std::os::raw::c_uint = 6;
|
pub const ETH_P_CAIF: u32 = 247;
|
||||||
pub const BPF_MISC: ::std::os::raw::c_uint = 7;
|
pub const ETH_P_XDSA: u32 = 248;
|
||||||
pub const BPF_W: ::std::os::raw::c_uint = 0;
|
pub const ETH_P_MAP: u32 = 249;
|
||||||
pub const BPF_H: ::std::os::raw::c_uint = 8;
|
pub const __UAPI_DEF_ETHHDR: u32 = 1;
|
||||||
pub const BPF_B: ::std::os::raw::c_uint = 16;
|
pub const BPF_LD: u32 = 0;
|
||||||
pub const BPF_IMM: ::std::os::raw::c_uint = 0;
|
pub const BPF_LDX: u32 = 1;
|
||||||
pub const BPF_ABS: ::std::os::raw::c_uint = 32;
|
pub const BPF_ST: u32 = 2;
|
||||||
pub const BPF_IND: ::std::os::raw::c_uint = 64;
|
pub const BPF_STX: u32 = 3;
|
||||||
pub const BPF_MEM: ::std::os::raw::c_uint = 96;
|
pub const BPF_ALU: u32 = 4;
|
||||||
pub const BPF_LEN: ::std::os::raw::c_uint = 128;
|
pub const BPF_JMP: u32 = 5;
|
||||||
pub const BPF_MSH: ::std::os::raw::c_uint = 160;
|
pub const BPF_RET: u32 = 6;
|
||||||
pub const BPF_ADD: ::std::os::raw::c_uint = 0;
|
pub const BPF_MISC: u32 = 7;
|
||||||
pub const BPF_SUB: ::std::os::raw::c_uint = 16;
|
pub const BPF_W: u32 = 0;
|
||||||
pub const BPF_MUL: ::std::os::raw::c_uint = 32;
|
pub const BPF_H: u32 = 8;
|
||||||
pub const BPF_DIV: ::std::os::raw::c_uint = 48;
|
pub const BPF_B: u32 = 16;
|
||||||
pub const BPF_OR: ::std::os::raw::c_uint = 64;
|
pub const BPF_IMM: u32 = 0;
|
||||||
pub const BPF_AND: ::std::os::raw::c_uint = 80;
|
pub const BPF_ABS: u32 = 32;
|
||||||
pub const BPF_LSH: ::std::os::raw::c_uint = 96;
|
pub const BPF_IND: u32 = 64;
|
||||||
pub const BPF_RSH: ::std::os::raw::c_uint = 112;
|
pub const BPF_MEM: u32 = 96;
|
||||||
pub const BPF_NEG: ::std::os::raw::c_uint = 128;
|
pub const BPF_LEN: u32 = 128;
|
||||||
pub const BPF_MOD: ::std::os::raw::c_uint = 144;
|
pub const BPF_MSH: u32 = 160;
|
||||||
pub const BPF_XOR: ::std::os::raw::c_uint = 160;
|
pub const BPF_ADD: u32 = 0;
|
||||||
pub const BPF_JA: ::std::os::raw::c_uint = 0;
|
pub const BPF_SUB: u32 = 16;
|
||||||
pub const BPF_JEQ: ::std::os::raw::c_uint = 16;
|
pub const BPF_MUL: u32 = 32;
|
||||||
pub const BPF_JGT: ::std::os::raw::c_uint = 32;
|
pub const BPF_DIV: u32 = 48;
|
||||||
pub const BPF_JGE: ::std::os::raw::c_uint = 48;
|
pub const BPF_OR: u32 = 64;
|
||||||
pub const BPF_JSET: ::std::os::raw::c_uint = 64;
|
pub const BPF_AND: u32 = 80;
|
||||||
pub const BPF_K: ::std::os::raw::c_uint = 0;
|
pub const BPF_LSH: u32 = 96;
|
||||||
pub const BPF_X: ::std::os::raw::c_uint = 8;
|
pub const BPF_RSH: u32 = 112;
|
||||||
pub const BPF_MAXINSNS: ::std::os::raw::c_uint = 4096;
|
pub const BPF_NEG: u32 = 128;
|
||||||
pub const BPF_MAJOR_VERSION: ::std::os::raw::c_uint = 1;
|
pub const BPF_MOD: u32 = 144;
|
||||||
pub const BPF_MINOR_VERSION: ::std::os::raw::c_uint = 1;
|
pub const BPF_XOR: u32 = 160;
|
||||||
pub const BPF_A: ::std::os::raw::c_uint = 16;
|
pub const BPF_JA: u32 = 0;
|
||||||
pub const BPF_TAX: ::std::os::raw::c_uint = 0;
|
pub const BPF_JEQ: u32 = 16;
|
||||||
pub const BPF_TXA: ::std::os::raw::c_uint = 128;
|
pub const BPF_JGT: u32 = 32;
|
||||||
pub const BPF_MEMWORDS: ::std::os::raw::c_uint = 16;
|
pub const BPF_JGE: u32 = 48;
|
||||||
pub const SKF_AD_OFF: ::std::os::raw::c_int = -4096;
|
pub const BPF_JSET: u32 = 64;
|
||||||
pub const SKF_AD_PROTOCOL: ::std::os::raw::c_uint = 0;
|
pub const BPF_K: u32 = 0;
|
||||||
pub const SKF_AD_PKTTYPE: ::std::os::raw::c_uint = 4;
|
pub const BPF_X: u32 = 8;
|
||||||
pub const SKF_AD_IFINDEX: ::std::os::raw::c_uint = 8;
|
pub const BPF_MAXINSNS: u32 = 4096;
|
||||||
pub const SKF_AD_NLATTR: ::std::os::raw::c_uint = 12;
|
pub const BPF_MAJOR_VERSION: u32 = 1;
|
||||||
pub const SKF_AD_NLATTR_NEST: ::std::os::raw::c_uint = 16;
|
pub const BPF_MINOR_VERSION: u32 = 1;
|
||||||
pub const SKF_AD_MARK: ::std::os::raw::c_uint = 20;
|
pub const BPF_A: u32 = 16;
|
||||||
pub const SKF_AD_QUEUE: ::std::os::raw::c_uint = 24;
|
pub const BPF_TAX: u32 = 0;
|
||||||
pub const SKF_AD_HATYPE: ::std::os::raw::c_uint = 28;
|
pub const BPF_TXA: u32 = 128;
|
||||||
pub const SKF_AD_RXHASH: ::std::os::raw::c_uint = 32;
|
pub const BPF_MEMWORDS: u32 = 16;
|
||||||
pub const SKF_AD_CPU: ::std::os::raw::c_uint = 36;
|
pub const SKF_AD_OFF: i32 = -4096;
|
||||||
pub const SKF_AD_ALU_XOR_X: ::std::os::raw::c_uint = 40;
|
pub const SKF_AD_PROTOCOL: u32 = 0;
|
||||||
pub const SKF_AD_VLAN_TAG: ::std::os::raw::c_uint = 44;
|
pub const SKF_AD_PKTTYPE: u32 = 4;
|
||||||
pub const SKF_AD_VLAN_TAG_PRESENT: ::std::os::raw::c_uint = 48;
|
pub const SKF_AD_IFINDEX: u32 = 8;
|
||||||
pub const SKF_AD_PAY_OFFSET: ::std::os::raw::c_uint = 52;
|
pub const SKF_AD_NLATTR: u32 = 12;
|
||||||
pub const SKF_AD_RANDOM: ::std::os::raw::c_uint = 56;
|
pub const SKF_AD_NLATTR_NEST: u32 = 16;
|
||||||
pub const SKF_AD_VLAN_TPID: ::std::os::raw::c_uint = 60;
|
pub const SKF_AD_MARK: u32 = 20;
|
||||||
pub const SKF_AD_MAX: ::std::os::raw::c_uint = 64;
|
pub const SKF_AD_QUEUE: u32 = 24;
|
||||||
pub const SKF_NET_OFF: ::std::os::raw::c_int = -1048576;
|
pub const SKF_AD_HATYPE: u32 = 28;
|
||||||
pub const SKF_LL_OFF: ::std::os::raw::c_int = -2097152;
|
pub const SKF_AD_RXHASH: u32 = 32;
|
||||||
pub const BPF_NET_OFF: ::std::os::raw::c_int = -1048576;
|
pub const SKF_AD_CPU: u32 = 36;
|
||||||
pub const BPF_LL_OFF: ::std::os::raw::c_int = -2097152;
|
pub const SKF_AD_ALU_XOR_X: u32 = 40;
|
||||||
pub const TUN_READQ_SIZE: ::std::os::raw::c_uint = 500;
|
pub const SKF_AD_VLAN_TAG: u32 = 44;
|
||||||
pub const TUN_TYPE_MASK: ::std::os::raw::c_uint = 15;
|
pub const SKF_AD_VLAN_TAG_PRESENT: u32 = 48;
|
||||||
pub const IFF_TUN: ::std::os::raw::c_uint = 1;
|
pub const SKF_AD_PAY_OFFSET: u32 = 52;
|
||||||
pub const IFF_TAP: ::std::os::raw::c_uint = 2;
|
pub const SKF_AD_RANDOM: u32 = 56;
|
||||||
pub const IFF_NO_PI: ::std::os::raw::c_uint = 4096;
|
pub const SKF_AD_VLAN_TPID: u32 = 60;
|
||||||
pub const IFF_ONE_QUEUE: ::std::os::raw::c_uint = 8192;
|
pub const SKF_AD_MAX: u32 = 64;
|
||||||
pub const IFF_VNET_HDR: ::std::os::raw::c_uint = 16384;
|
pub const SKF_NET_OFF: i32 = -1048576;
|
||||||
pub const IFF_TUN_EXCL: ::std::os::raw::c_uint = 32768;
|
pub const SKF_LL_OFF: i32 = -2097152;
|
||||||
pub const IFF_MULTI_QUEUE: ::std::os::raw::c_uint = 256;
|
pub const BPF_NET_OFF: i32 = -1048576;
|
||||||
pub const IFF_ATTACH_QUEUE: ::std::os::raw::c_uint = 512;
|
pub const BPF_LL_OFF: i32 = -2097152;
|
||||||
pub const IFF_DETACH_QUEUE: ::std::os::raw::c_uint = 1024;
|
pub const TUN_READQ_SIZE: u32 = 500;
|
||||||
pub const IFF_PERSIST: ::std::os::raw::c_uint = 2048;
|
pub const TUN_TYPE_MASK: u32 = 15;
|
||||||
pub const IFF_NOFILTER: ::std::os::raw::c_uint = 4096;
|
pub const IFF_TUN: u32 = 1;
|
||||||
pub const TUN_TX_TIMESTAMP: ::std::os::raw::c_uint = 1;
|
pub const IFF_TAP: u32 = 2;
|
||||||
pub const TUN_F_CSUM: ::std::os::raw::c_uint = 1;
|
pub const IFF_NAPI: u32 = 16;
|
||||||
pub const TUN_F_TSO4: ::std::os::raw::c_uint = 2;
|
pub const IFF_NAPI_FRAGS: u32 = 32;
|
||||||
pub const TUN_F_TSO6: ::std::os::raw::c_uint = 4;
|
pub const IFF_NO_PI: u32 = 4096;
|
||||||
pub const TUN_F_TSO_ECN: ::std::os::raw::c_uint = 8;
|
pub const IFF_ONE_QUEUE: u32 = 8192;
|
||||||
pub const TUN_F_UFO: ::std::os::raw::c_uint = 16;
|
pub const IFF_VNET_HDR: u32 = 16384;
|
||||||
pub const TUN_PKT_STRIP: ::std::os::raw::c_uint = 1;
|
pub const IFF_TUN_EXCL: u32 = 32768;
|
||||||
pub const TUN_FLT_ALLMULTI: ::std::os::raw::c_uint = 1;
|
pub const IFF_MULTI_QUEUE: u32 = 256;
|
||||||
|
pub const IFF_ATTACH_QUEUE: u32 = 512;
|
||||||
|
pub const IFF_DETACH_QUEUE: u32 = 1024;
|
||||||
|
pub const IFF_PERSIST: u32 = 2048;
|
||||||
|
pub const IFF_NOFILTER: u32 = 4096;
|
||||||
|
pub const TUN_TX_TIMESTAMP: u32 = 1;
|
||||||
|
pub const TUN_F_CSUM: u32 = 1;
|
||||||
|
pub const TUN_F_TSO4: u32 = 2;
|
||||||
|
pub const TUN_F_TSO6: u32 = 4;
|
||||||
|
pub const TUN_F_TSO_ECN: u32 = 8;
|
||||||
|
pub const TUN_F_UFO: u32 = 16;
|
||||||
|
pub const TUN_PKT_STRIP: u32 = 1;
|
||||||
|
pub const TUN_FLT_ALLMULTI: u32 = 1;
|
||||||
pub type __s8 = ::std::os::raw::c_schar;
|
pub type __s8 = ::std::os::raw::c_schar;
|
||||||
pub type __u8 = ::std::os::raw::c_uchar;
|
pub type __u8 = ::std::os::raw::c_uchar;
|
||||||
pub type __s16 = ::std::os::raw::c_short;
|
pub type __s16 = ::std::os::raw::c_short;
|
||||||
@@ -224,38 +239,10 @@ pub type __u32 = ::std::os::raw::c_uint;
|
|||||||
pub type __s64 = ::std::os::raw::c_longlong;
|
pub type __s64 = ::std::os::raw::c_longlong;
|
||||||
pub type __u64 = ::std::os::raw::c_ulonglong;
|
pub type __u64 = ::std::os::raw::c_ulonglong;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct __kernel_fd_set {
|
pub struct __kernel_fd_set {
|
||||||
pub fds_bits: [::std::os::raw::c_ulong; 16usize],
|
pub fds_bits: [::std::os::raw::c_ulong; 16usize],
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout___kernel_fd_set() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<__kernel_fd_set>(),
|
|
||||||
128usize,
|
|
||||||
concat!("Size of: ", stringify!(__kernel_fd_set))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<__kernel_fd_set>(),
|
|
||||||
8usize,
|
|
||||||
concat!("Alignment of ", stringify!(__kernel_fd_set))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const __kernel_fd_set)).fds_bits as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(__kernel_fd_set),
|
|
||||||
"::",
|
|
||||||
stringify!(fds_bits)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for __kernel_fd_set {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub type __kernel_sighandler_t =
|
pub type __kernel_sighandler_t =
|
||||||
::std::option::Option<unsafe extern "C" fn(arg1: ::std::os::raw::c_int)>;
|
::std::option::Option<unsafe extern "C" fn(arg1: ::std::os::raw::c_int)>;
|
||||||
pub type __kernel_key_t = ::std::os::raw::c_int;
|
pub type __kernel_key_t = ::std::os::raw::c_int;
|
||||||
@@ -279,41 +266,15 @@ pub type __kernel_size_t = __kernel_ulong_t;
|
|||||||
pub type __kernel_ssize_t = __kernel_long_t;
|
pub type __kernel_ssize_t = __kernel_long_t;
|
||||||
pub type __kernel_ptrdiff_t = __kernel_long_t;
|
pub type __kernel_ptrdiff_t = __kernel_long_t;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct __kernel_fsid_t {
|
pub struct __kernel_fsid_t {
|
||||||
pub val: [::std::os::raw::c_int; 2usize],
|
pub val: [::std::os::raw::c_int; 2usize],
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout___kernel_fsid_t() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<__kernel_fsid_t>(),
|
|
||||||
8usize,
|
|
||||||
concat!("Size of: ", stringify!(__kernel_fsid_t))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<__kernel_fsid_t>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Alignment of ", stringify!(__kernel_fsid_t))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const __kernel_fsid_t)).val as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(__kernel_fsid_t),
|
|
||||||
"::",
|
|
||||||
stringify!(val)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for __kernel_fsid_t {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub type __kernel_off_t = __kernel_long_t;
|
pub type __kernel_off_t = __kernel_long_t;
|
||||||
pub type __kernel_loff_t = ::std::os::raw::c_longlong;
|
pub type __kernel_loff_t = ::std::os::raw::c_longlong;
|
||||||
|
pub type __kernel_old_time_t = __kernel_long_t;
|
||||||
pub type __kernel_time_t = __kernel_long_t;
|
pub type __kernel_time_t = __kernel_long_t;
|
||||||
|
pub type __kernel_time64_t = ::std::os::raw::c_longlong;
|
||||||
pub type __kernel_clock_t = __kernel_long_t;
|
pub type __kernel_clock_t = __kernel_long_t;
|
||||||
pub type __kernel_timer_t = ::std::os::raw::c_int;
|
pub type __kernel_timer_t = ::std::os::raw::c_int;
|
||||||
pub type __kernel_clockid_t = ::std::os::raw::c_int;
|
pub type __kernel_clockid_t = ::std::os::raw::c_int;
|
||||||
@@ -328,272 +289,38 @@ pub type __le64 = __u64;
|
|||||||
pub type __be64 = __u64;
|
pub type __be64 = __u64;
|
||||||
pub type __sum16 = __u16;
|
pub type __sum16 = __u16;
|
||||||
pub type __wsum = __u32;
|
pub type __wsum = __u32;
|
||||||
|
pub type __poll_t = ::std::os::raw::c_uint;
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct ethhdr {
|
pub struct ethhdr {
|
||||||
pub h_dest: [::std::os::raw::c_uchar; 6usize],
|
pub h_dest: [::std::os::raw::c_uchar; 6usize],
|
||||||
pub h_source: [::std::os::raw::c_uchar; 6usize],
|
pub h_source: [::std::os::raw::c_uchar; 6usize],
|
||||||
pub h_proto: __be16,
|
pub h_proto: __be16,
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_ethhdr() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<ethhdr>(),
|
|
||||||
14usize,
|
|
||||||
concat!("Size of: ", stringify!(ethhdr))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<ethhdr>(),
|
|
||||||
1usize,
|
|
||||||
concat!("Alignment of ", stringify!(ethhdr))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const ethhdr)).h_dest as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(ethhdr),
|
|
||||||
"::",
|
|
||||||
stringify!(h_dest)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const ethhdr)).h_source as *const _ as usize },
|
|
||||||
6usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(ethhdr),
|
|
||||||
"::",
|
|
||||||
stringify!(h_source)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const ethhdr)).h_proto as *const _ as usize },
|
|
||||||
12usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(ethhdr),
|
|
||||||
"::",
|
|
||||||
stringify!(h_proto)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for ethhdr {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct sock_filter {
|
pub struct sock_filter {
|
||||||
pub code: __u16,
|
pub code: __u16,
|
||||||
pub jt: __u8,
|
pub jt: __u8,
|
||||||
pub jf: __u8,
|
pub jf: __u8,
|
||||||
pub k: __u32,
|
pub k: __u32,
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_sock_filter() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<sock_filter>(),
|
|
||||||
8usize,
|
|
||||||
concat!("Size of: ", stringify!(sock_filter))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<sock_filter>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Alignment of ", stringify!(sock_filter))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const sock_filter)).code as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(sock_filter),
|
|
||||||
"::",
|
|
||||||
stringify!(code)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const sock_filter)).jt as *const _ as usize },
|
|
||||||
2usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(sock_filter),
|
|
||||||
"::",
|
|
||||||
stringify!(jt)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const sock_filter)).jf as *const _ as usize },
|
|
||||||
3usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(sock_filter),
|
|
||||||
"::",
|
|
||||||
stringify!(jf)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const sock_filter)).k as *const _ as usize },
|
|
||||||
4usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(sock_filter),
|
|
||||||
"::",
|
|
||||||
stringify!(k)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for sock_filter {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct sock_fprog {
|
pub struct sock_fprog {
|
||||||
pub len: ::std::os::raw::c_ushort,
|
pub len: ::std::os::raw::c_ushort,
|
||||||
pub filter: *mut sock_filter,
|
pub filter: *mut sock_filter,
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_sock_fprog() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<sock_fprog>(),
|
|
||||||
16usize,
|
|
||||||
concat!("Size of: ", stringify!(sock_fprog))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<sock_fprog>(),
|
|
||||||
8usize,
|
|
||||||
concat!("Alignment of ", stringify!(sock_fprog))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const sock_fprog)).len as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(sock_fprog),
|
|
||||||
"::",
|
|
||||||
stringify!(len)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const sock_fprog)).filter as *const _ as usize },
|
|
||||||
8usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(sock_fprog),
|
|
||||||
"::",
|
|
||||||
stringify!(filter)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for sock_fprog {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Default for sock_fprog {
|
|
||||||
fn default() -> Self {
|
|
||||||
unsafe { ::std::mem::zeroed() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct tun_pi {
|
pub struct tun_pi {
|
||||||
pub flags: __u16,
|
pub flags: __u16,
|
||||||
pub proto: __be16,
|
pub proto: __be16,
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_tun_pi() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<tun_pi>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Size of: ", stringify!(tun_pi))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<tun_pi>(),
|
|
||||||
2usize,
|
|
||||||
concat!("Alignment of ", stringify!(tun_pi))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const tun_pi)).flags as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(tun_pi),
|
|
||||||
"::",
|
|
||||||
stringify!(flags)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const tun_pi)).proto as *const _ as usize },
|
|
||||||
2usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(tun_pi),
|
|
||||||
"::",
|
|
||||||
stringify!(proto)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for tun_pi {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug)]
|
||||||
pub struct tun_filter {
|
pub struct tun_filter {
|
||||||
pub flags: __u16,
|
pub flags: __u16,
|
||||||
pub count: __u16,
|
pub count: __u16,
|
||||||
pub addr: __IncompleteArrayField<[__u8; 6usize]>,
|
pub addr: __IncompleteArrayField<[__u8; 6usize]>,
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_tun_filter() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<tun_filter>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Size of: ", stringify!(tun_filter))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<tun_filter>(),
|
|
||||||
2usize,
|
|
||||||
concat!("Alignment of ", stringify!(tun_filter))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const tun_filter)).flags as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(tun_filter),
|
|
||||||
"::",
|
|
||||||
stringify!(flags)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const tun_filter)).count as *const _ as usize },
|
|
||||||
2usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(tun_filter),
|
|
||||||
"::",
|
|
||||||
stringify!(count)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const tun_filter)).addr as *const _ as usize },
|
|
||||||
4usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(tun_filter),
|
|
||||||
"::",
|
|
||||||
stringify!(addr)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for tun_filter {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
3464
net_gen/src/iff.rs
3464
net_gen/src/iff.rs
File diff suppressed because it is too large
Load Diff
@@ -1,103 +1,119 @@
|
|||||||
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
// Copyright © 2021 Intel Corporation
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
//
|
||||||
// found in the THIRD-PARTY file.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
/* automatically generated by rust-bindgen */
|
// bindgen /usr/include/linux/in.h --no-layout-tests
|
||||||
|
|
||||||
pub const __BITS_PER_LONG: ::std::os::raw::c_uint = 64;
|
/* automatically generated by rust-bindgen 0.58.1 */
|
||||||
pub const __FD_SETSIZE: ::std::os::raw::c_uint = 1024;
|
|
||||||
pub const __UAPI_DEF_IN_ADDR: ::std::os::raw::c_uint = 1;
|
pub const __BITS_PER_LONG: u32 = 64;
|
||||||
pub const __UAPI_DEF_IN_IPPROTO: ::std::os::raw::c_uint = 1;
|
pub const __FD_SETSIZE: u32 = 1024;
|
||||||
pub const __UAPI_DEF_IN_PKTINFO: ::std::os::raw::c_uint = 1;
|
pub const __UAPI_DEF_IF_IFCONF: u32 = 1;
|
||||||
pub const __UAPI_DEF_IP_MREQ: ::std::os::raw::c_uint = 1;
|
pub const __UAPI_DEF_IF_IFMAP: u32 = 1;
|
||||||
pub const __UAPI_DEF_SOCKADDR_IN: ::std::os::raw::c_uint = 1;
|
pub const __UAPI_DEF_IF_IFNAMSIZ: u32 = 1;
|
||||||
pub const __UAPI_DEF_IN_CLASS: ::std::os::raw::c_uint = 1;
|
pub const __UAPI_DEF_IF_IFREQ: u32 = 1;
|
||||||
pub const __UAPI_DEF_IN6_ADDR: ::std::os::raw::c_uint = 1;
|
pub const __UAPI_DEF_IF_NET_DEVICE_FLAGS: u32 = 1;
|
||||||
pub const __UAPI_DEF_IN6_ADDR_ALT: ::std::os::raw::c_uint = 1;
|
pub const __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO: u32 = 1;
|
||||||
pub const __UAPI_DEF_SOCKADDR_IN6: ::std::os::raw::c_uint = 1;
|
pub const __UAPI_DEF_IN_ADDR: u32 = 1;
|
||||||
pub const __UAPI_DEF_IPV6_MREQ: ::std::os::raw::c_uint = 1;
|
pub const __UAPI_DEF_IN_IPPROTO: u32 = 1;
|
||||||
pub const __UAPI_DEF_IPPROTO_V6: ::std::os::raw::c_uint = 1;
|
pub const __UAPI_DEF_IN_PKTINFO: u32 = 1;
|
||||||
pub const __UAPI_DEF_IPV6_OPTIONS: ::std::os::raw::c_uint = 1;
|
pub const __UAPI_DEF_IP_MREQ: u32 = 1;
|
||||||
pub const __UAPI_DEF_IN6_PKTINFO: ::std::os::raw::c_uint = 1;
|
pub const __UAPI_DEF_SOCKADDR_IN: u32 = 1;
|
||||||
pub const __UAPI_DEF_IP6_MTUINFO: ::std::os::raw::c_uint = 1;
|
pub const __UAPI_DEF_IN_CLASS: u32 = 1;
|
||||||
pub const __UAPI_DEF_XATTR: ::std::os::raw::c_uint = 1;
|
pub const __UAPI_DEF_IN6_ADDR: u32 = 1;
|
||||||
pub const _K_SS_MAXSIZE: ::std::os::raw::c_uint = 128;
|
pub const __UAPI_DEF_IN6_ADDR_ALT: u32 = 1;
|
||||||
pub const IP_TOS: ::std::os::raw::c_uint = 1;
|
pub const __UAPI_DEF_SOCKADDR_IN6: u32 = 1;
|
||||||
pub const IP_TTL: ::std::os::raw::c_uint = 2;
|
pub const __UAPI_DEF_IPV6_MREQ: u32 = 1;
|
||||||
pub const IP_HDRINCL: ::std::os::raw::c_uint = 3;
|
pub const __UAPI_DEF_IPPROTO_V6: u32 = 1;
|
||||||
pub const IP_OPTIONS: ::std::os::raw::c_uint = 4;
|
pub const __UAPI_DEF_IPV6_OPTIONS: u32 = 1;
|
||||||
pub const IP_ROUTER_ALERT: ::std::os::raw::c_uint = 5;
|
pub const __UAPI_DEF_IN6_PKTINFO: u32 = 1;
|
||||||
pub const IP_RECVOPTS: ::std::os::raw::c_uint = 6;
|
pub const __UAPI_DEF_IP6_MTUINFO: u32 = 1;
|
||||||
pub const IP_RETOPTS: ::std::os::raw::c_uint = 7;
|
pub const __UAPI_DEF_SOCKADDR_IPX: u32 = 1;
|
||||||
pub const IP_PKTINFO: ::std::os::raw::c_uint = 8;
|
pub const __UAPI_DEF_IPX_ROUTE_DEFINITION: u32 = 1;
|
||||||
pub const IP_PKTOPTIONS: ::std::os::raw::c_uint = 9;
|
pub const __UAPI_DEF_IPX_INTERFACE_DEFINITION: u32 = 1;
|
||||||
pub const IP_MTU_DISCOVER: ::std::os::raw::c_uint = 10;
|
pub const __UAPI_DEF_IPX_CONFIG_DATA: u32 = 1;
|
||||||
pub const IP_RECVERR: ::std::os::raw::c_uint = 11;
|
pub const __UAPI_DEF_IPX_ROUTE_DEF: u32 = 1;
|
||||||
pub const IP_RECVTTL: ::std::os::raw::c_uint = 12;
|
pub const __UAPI_DEF_XATTR: u32 = 1;
|
||||||
pub const IP_RECVTOS: ::std::os::raw::c_uint = 13;
|
pub const _K_SS_MAXSIZE: u32 = 128;
|
||||||
pub const IP_MTU: ::std::os::raw::c_uint = 14;
|
pub const IP_TOS: u32 = 1;
|
||||||
pub const IP_FREEBIND: ::std::os::raw::c_uint = 15;
|
pub const IP_TTL: u32 = 2;
|
||||||
pub const IP_IPSEC_POLICY: ::std::os::raw::c_uint = 16;
|
pub const IP_HDRINCL: u32 = 3;
|
||||||
pub const IP_XFRM_POLICY: ::std::os::raw::c_uint = 17;
|
pub const IP_OPTIONS: u32 = 4;
|
||||||
pub const IP_PASSSEC: ::std::os::raw::c_uint = 18;
|
pub const IP_ROUTER_ALERT: u32 = 5;
|
||||||
pub const IP_TRANSPARENT: ::std::os::raw::c_uint = 19;
|
pub const IP_RECVOPTS: u32 = 6;
|
||||||
pub const IP_RECVRETOPTS: ::std::os::raw::c_uint = 7;
|
pub const IP_RETOPTS: u32 = 7;
|
||||||
pub const IP_ORIGDSTADDR: ::std::os::raw::c_uint = 20;
|
pub const IP_PKTINFO: u32 = 8;
|
||||||
pub const IP_RECVORIGDSTADDR: ::std::os::raw::c_uint = 20;
|
pub const IP_PKTOPTIONS: u32 = 9;
|
||||||
pub const IP_MINTTL: ::std::os::raw::c_uint = 21;
|
pub const IP_MTU_DISCOVER: u32 = 10;
|
||||||
pub const IP_NODEFRAG: ::std::os::raw::c_uint = 22;
|
pub const IP_RECVERR: u32 = 11;
|
||||||
pub const IP_CHECKSUM: ::std::os::raw::c_uint = 23;
|
pub const IP_RECVTTL: u32 = 12;
|
||||||
pub const IP_BIND_ADDRESS_NO_PORT: ::std::os::raw::c_uint = 24;
|
pub const IP_RECVTOS: u32 = 13;
|
||||||
pub const IP_RECVFRAGSIZE: ::std::os::raw::c_uint = 25;
|
pub const IP_MTU: u32 = 14;
|
||||||
pub const IP_PMTUDISC_DONT: ::std::os::raw::c_uint = 0;
|
pub const IP_FREEBIND: u32 = 15;
|
||||||
pub const IP_PMTUDISC_WANT: ::std::os::raw::c_uint = 1;
|
pub const IP_IPSEC_POLICY: u32 = 16;
|
||||||
pub const IP_PMTUDISC_DO: ::std::os::raw::c_uint = 2;
|
pub const IP_XFRM_POLICY: u32 = 17;
|
||||||
pub const IP_PMTUDISC_PROBE: ::std::os::raw::c_uint = 3;
|
pub const IP_PASSSEC: u32 = 18;
|
||||||
pub const IP_PMTUDISC_INTERFACE: ::std::os::raw::c_uint = 4;
|
pub const IP_TRANSPARENT: u32 = 19;
|
||||||
pub const IP_PMTUDISC_OMIT: ::std::os::raw::c_uint = 5;
|
pub const IP_RECVRETOPTS: u32 = 7;
|
||||||
pub const IP_MULTICAST_IF: ::std::os::raw::c_uint = 32;
|
pub const IP_ORIGDSTADDR: u32 = 20;
|
||||||
pub const IP_MULTICAST_TTL: ::std::os::raw::c_uint = 33;
|
pub const IP_RECVORIGDSTADDR: u32 = 20;
|
||||||
pub const IP_MULTICAST_LOOP: ::std::os::raw::c_uint = 34;
|
pub const IP_MINTTL: u32 = 21;
|
||||||
pub const IP_ADD_MEMBERSHIP: ::std::os::raw::c_uint = 35;
|
pub const IP_NODEFRAG: u32 = 22;
|
||||||
pub const IP_DROP_MEMBERSHIP: ::std::os::raw::c_uint = 36;
|
pub const IP_CHECKSUM: u32 = 23;
|
||||||
pub const IP_UNBLOCK_SOURCE: ::std::os::raw::c_uint = 37;
|
pub const IP_BIND_ADDRESS_NO_PORT: u32 = 24;
|
||||||
pub const IP_BLOCK_SOURCE: ::std::os::raw::c_uint = 38;
|
pub const IP_RECVFRAGSIZE: u32 = 25;
|
||||||
pub const IP_ADD_SOURCE_MEMBERSHIP: ::std::os::raw::c_uint = 39;
|
pub const IP_PMTUDISC_DONT: u32 = 0;
|
||||||
pub const IP_DROP_SOURCE_MEMBERSHIP: ::std::os::raw::c_uint = 40;
|
pub const IP_PMTUDISC_WANT: u32 = 1;
|
||||||
pub const IP_MSFILTER: ::std::os::raw::c_uint = 41;
|
pub const IP_PMTUDISC_DO: u32 = 2;
|
||||||
pub const MCAST_JOIN_GROUP: ::std::os::raw::c_uint = 42;
|
pub const IP_PMTUDISC_PROBE: u32 = 3;
|
||||||
pub const MCAST_BLOCK_SOURCE: ::std::os::raw::c_uint = 43;
|
pub const IP_PMTUDISC_INTERFACE: u32 = 4;
|
||||||
pub const MCAST_UNBLOCK_SOURCE: ::std::os::raw::c_uint = 44;
|
pub const IP_PMTUDISC_OMIT: u32 = 5;
|
||||||
pub const MCAST_LEAVE_GROUP: ::std::os::raw::c_uint = 45;
|
pub const IP_MULTICAST_IF: u32 = 32;
|
||||||
pub const MCAST_JOIN_SOURCE_GROUP: ::std::os::raw::c_uint = 46;
|
pub const IP_MULTICAST_TTL: u32 = 33;
|
||||||
pub const MCAST_LEAVE_SOURCE_GROUP: ::std::os::raw::c_uint = 47;
|
pub const IP_MULTICAST_LOOP: u32 = 34;
|
||||||
pub const MCAST_MSFILTER: ::std::os::raw::c_uint = 48;
|
pub const IP_ADD_MEMBERSHIP: u32 = 35;
|
||||||
pub const IP_MULTICAST_ALL: ::std::os::raw::c_uint = 49;
|
pub const IP_DROP_MEMBERSHIP: u32 = 36;
|
||||||
pub const IP_UNICAST_IF: ::std::os::raw::c_uint = 50;
|
pub const IP_UNBLOCK_SOURCE: u32 = 37;
|
||||||
pub const MCAST_EXCLUDE: ::std::os::raw::c_uint = 0;
|
pub const IP_BLOCK_SOURCE: u32 = 38;
|
||||||
pub const MCAST_INCLUDE: ::std::os::raw::c_uint = 1;
|
pub const IP_ADD_SOURCE_MEMBERSHIP: u32 = 39;
|
||||||
pub const IP_DEFAULT_MULTICAST_TTL: ::std::os::raw::c_uint = 1;
|
pub const IP_DROP_SOURCE_MEMBERSHIP: u32 = 40;
|
||||||
pub const IP_DEFAULT_MULTICAST_LOOP: ::std::os::raw::c_uint = 1;
|
pub const IP_MSFILTER: u32 = 41;
|
||||||
pub const __SOCK_SIZE__: ::std::os::raw::c_uint = 16;
|
pub const MCAST_JOIN_GROUP: u32 = 42;
|
||||||
pub const IN_CLASSA_NET: ::std::os::raw::c_uint = 4278190080;
|
pub const MCAST_BLOCK_SOURCE: u32 = 43;
|
||||||
pub const IN_CLASSA_NSHIFT: ::std::os::raw::c_uint = 24;
|
pub const MCAST_UNBLOCK_SOURCE: u32 = 44;
|
||||||
pub const IN_CLASSA_HOST: ::std::os::raw::c_uint = 16777215;
|
pub const MCAST_LEAVE_GROUP: u32 = 45;
|
||||||
pub const IN_CLASSA_MAX: ::std::os::raw::c_uint = 128;
|
pub const MCAST_JOIN_SOURCE_GROUP: u32 = 46;
|
||||||
pub const IN_CLASSB_NET: ::std::os::raw::c_uint = 4294901760;
|
pub const MCAST_LEAVE_SOURCE_GROUP: u32 = 47;
|
||||||
pub const IN_CLASSB_NSHIFT: ::std::os::raw::c_uint = 16;
|
pub const MCAST_MSFILTER: u32 = 48;
|
||||||
pub const IN_CLASSB_HOST: ::std::os::raw::c_uint = 65535;
|
pub const IP_MULTICAST_ALL: u32 = 49;
|
||||||
pub const IN_CLASSB_MAX: ::std::os::raw::c_uint = 65536;
|
pub const IP_UNICAST_IF: u32 = 50;
|
||||||
pub const IN_CLASSC_NET: ::std::os::raw::c_uint = 4294967040;
|
pub const MCAST_EXCLUDE: u32 = 0;
|
||||||
pub const IN_CLASSC_NSHIFT: ::std::os::raw::c_uint = 8;
|
pub const MCAST_INCLUDE: u32 = 1;
|
||||||
pub const IN_CLASSC_HOST: ::std::os::raw::c_uint = 255;
|
pub const IP_DEFAULT_MULTICAST_TTL: u32 = 1;
|
||||||
pub const IN_MULTICAST_NET: ::std::os::raw::c_uint = 4026531840;
|
pub const IP_DEFAULT_MULTICAST_LOOP: u32 = 1;
|
||||||
pub const IN_LOOPBACKNET: ::std::os::raw::c_uint = 127;
|
pub const __SOCK_SIZE__: u32 = 16;
|
||||||
pub const INADDR_LOOPBACK: ::std::os::raw::c_uint = 2130706433;
|
pub const IN_CLASSA_NET: u32 = 4278190080;
|
||||||
pub const INADDR_UNSPEC_GROUP: ::std::os::raw::c_uint = 3758096384;
|
pub const IN_CLASSA_NSHIFT: u32 = 24;
|
||||||
pub const INADDR_ALLHOSTS_GROUP: ::std::os::raw::c_uint = 3758096385;
|
pub const IN_CLASSA_HOST: u32 = 16777215;
|
||||||
pub const INADDR_ALLRTRS_GROUP: ::std::os::raw::c_uint = 3758096386;
|
pub const IN_CLASSA_MAX: u32 = 128;
|
||||||
pub const INADDR_MAX_LOCAL_GROUP: ::std::os::raw::c_uint = 3758096639;
|
pub const IN_CLASSB_NET: u32 = 4294901760;
|
||||||
pub const __LITTLE_ENDIAN: ::std::os::raw::c_uint = 1234;
|
pub const IN_CLASSB_NSHIFT: u32 = 16;
|
||||||
|
pub const IN_CLASSB_HOST: u32 = 65535;
|
||||||
|
pub const IN_CLASSB_MAX: u32 = 65536;
|
||||||
|
pub const IN_CLASSC_NET: u32 = 4294967040;
|
||||||
|
pub const IN_CLASSC_NSHIFT: u32 = 8;
|
||||||
|
pub const IN_CLASSC_HOST: u32 = 255;
|
||||||
|
pub const IN_MULTICAST_NET: u32 = 3758096384;
|
||||||
|
pub const IN_CLASSE_NET: u32 = 4294967295;
|
||||||
|
pub const IN_CLASSE_NSHIFT: u32 = 0;
|
||||||
|
pub const IN_LOOPBACKNET: u32 = 127;
|
||||||
|
pub const INADDR_LOOPBACK: u32 = 2130706433;
|
||||||
|
pub const INADDR_UNSPEC_GROUP: u32 = 3758096384;
|
||||||
|
pub const INADDR_ALLHOSTS_GROUP: u32 = 3758096385;
|
||||||
|
pub const INADDR_ALLRTRS_GROUP: u32 = 3758096386;
|
||||||
|
pub const INADDR_ALLSNOOPERS_GROUP: u32 = 3758096490;
|
||||||
|
pub const INADDR_MAX_LOCAL_GROUP: u32 = 3758096639;
|
||||||
|
pub const __LITTLE_ENDIAN: u32 = 1234;
|
||||||
pub type __s8 = ::std::os::raw::c_schar;
|
pub type __s8 = ::std::os::raw::c_schar;
|
||||||
pub type __u8 = ::std::os::raw::c_uchar;
|
pub type __u8 = ::std::os::raw::c_uchar;
|
||||||
pub type __s16 = ::std::os::raw::c_short;
|
pub type __s16 = ::std::os::raw::c_short;
|
||||||
@@ -107,38 +123,10 @@ pub type __u32 = ::std::os::raw::c_uint;
|
|||||||
pub type __s64 = ::std::os::raw::c_longlong;
|
pub type __s64 = ::std::os::raw::c_longlong;
|
||||||
pub type __u64 = ::std::os::raw::c_ulonglong;
|
pub type __u64 = ::std::os::raw::c_ulonglong;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct __kernel_fd_set {
|
pub struct __kernel_fd_set {
|
||||||
pub fds_bits: [::std::os::raw::c_ulong; 16usize],
|
pub fds_bits: [::std::os::raw::c_ulong; 16usize],
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout___kernel_fd_set() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<__kernel_fd_set>(),
|
|
||||||
128usize,
|
|
||||||
concat!("Size of: ", stringify!(__kernel_fd_set))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<__kernel_fd_set>(),
|
|
||||||
8usize,
|
|
||||||
concat!("Alignment of ", stringify!(__kernel_fd_set))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const __kernel_fd_set)).fds_bits as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(__kernel_fd_set),
|
|
||||||
"::",
|
|
||||||
stringify!(fds_bits)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for __kernel_fd_set {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub type __kernel_sighandler_t =
|
pub type __kernel_sighandler_t =
|
||||||
::std::option::Option<unsafe extern "C" fn(arg1: ::std::os::raw::c_int)>;
|
::std::option::Option<unsafe extern "C" fn(arg1: ::std::os::raw::c_int)>;
|
||||||
pub type __kernel_key_t = ::std::os::raw::c_int;
|
pub type __kernel_key_t = ::std::os::raw::c_int;
|
||||||
@@ -162,41 +150,15 @@ pub type __kernel_size_t = __kernel_ulong_t;
|
|||||||
pub type __kernel_ssize_t = __kernel_long_t;
|
pub type __kernel_ssize_t = __kernel_long_t;
|
||||||
pub type __kernel_ptrdiff_t = __kernel_long_t;
|
pub type __kernel_ptrdiff_t = __kernel_long_t;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct __kernel_fsid_t {
|
pub struct __kernel_fsid_t {
|
||||||
pub val: [::std::os::raw::c_int; 2usize],
|
pub val: [::std::os::raw::c_int; 2usize],
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout___kernel_fsid_t() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<__kernel_fsid_t>(),
|
|
||||||
8usize,
|
|
||||||
concat!("Size of: ", stringify!(__kernel_fsid_t))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<__kernel_fsid_t>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Alignment of ", stringify!(__kernel_fsid_t))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const __kernel_fsid_t)).val as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(__kernel_fsid_t),
|
|
||||||
"::",
|
|
||||||
stringify!(val)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for __kernel_fsid_t {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub type __kernel_off_t = __kernel_long_t;
|
pub type __kernel_off_t = __kernel_long_t;
|
||||||
pub type __kernel_loff_t = ::std::os::raw::c_longlong;
|
pub type __kernel_loff_t = ::std::os::raw::c_longlong;
|
||||||
|
pub type __kernel_old_time_t = __kernel_long_t;
|
||||||
pub type __kernel_time_t = __kernel_long_t;
|
pub type __kernel_time_t = __kernel_long_t;
|
||||||
|
pub type __kernel_time64_t = ::std::os::raw::c_longlong;
|
||||||
pub type __kernel_clock_t = __kernel_long_t;
|
pub type __kernel_clock_t = __kernel_long_t;
|
||||||
pub type __kernel_timer_t = ::std::os::raw::c_int;
|
pub type __kernel_timer_t = ::std::os::raw::c_int;
|
||||||
pub type __kernel_clockid_t = ::std::os::raw::c_int;
|
pub type __kernel_clockid_t = ::std::os::raw::c_int;
|
||||||
@@ -211,267 +173,81 @@ pub type __le64 = __u64;
|
|||||||
pub type __be64 = __u64;
|
pub type __be64 = __u64;
|
||||||
pub type __sum16 = __u16;
|
pub type __sum16 = __u16;
|
||||||
pub type __wsum = __u32;
|
pub type __wsum = __u32;
|
||||||
|
pub type __poll_t = ::std::os::raw::c_uint;
|
||||||
pub type __kernel_sa_family_t = ::std::os::raw::c_ushort;
|
pub type __kernel_sa_family_t = ::std::os::raw::c_ushort;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
pub struct __kernel_sockaddr_storage {
|
pub struct __kernel_sockaddr_storage {
|
||||||
|
pub __bindgen_anon_1: __kernel_sockaddr_storage__bindgen_ty_1,
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub union __kernel_sockaddr_storage__bindgen_ty_1 {
|
||||||
|
pub __bindgen_anon_1: __kernel_sockaddr_storage__bindgen_ty_1__bindgen_ty_1,
|
||||||
|
pub __align: *mut ::std::os::raw::c_void,
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct __kernel_sockaddr_storage__bindgen_ty_1__bindgen_ty_1 {
|
||||||
pub ss_family: __kernel_sa_family_t,
|
pub ss_family: __kernel_sa_family_t,
|
||||||
pub __data: [::std::os::raw::c_char; 126usize],
|
pub __data: [::std::os::raw::c_char; 126usize],
|
||||||
pub __bindgen_align: [u64; 0usize],
|
|
||||||
}
|
}
|
||||||
#[test]
|
pub const IPPROTO_IP: ::std::os::raw::c_uint = 0;
|
||||||
fn bindgen_test_layout___kernel_sockaddr_storage() {
|
pub const IPPROTO_ICMP: ::std::os::raw::c_uint = 1;
|
||||||
assert_eq!(
|
pub const IPPROTO_IGMP: ::std::os::raw::c_uint = 2;
|
||||||
::std::mem::size_of::<__kernel_sockaddr_storage>(),
|
pub const IPPROTO_IPIP: ::std::os::raw::c_uint = 4;
|
||||||
128usize,
|
pub const IPPROTO_TCP: ::std::os::raw::c_uint = 6;
|
||||||
concat!("Size of: ", stringify!(__kernel_sockaddr_storage))
|
pub const IPPROTO_EGP: ::std::os::raw::c_uint = 8;
|
||||||
);
|
pub const IPPROTO_PUP: ::std::os::raw::c_uint = 12;
|
||||||
assert_eq!(
|
pub const IPPROTO_UDP: ::std::os::raw::c_uint = 17;
|
||||||
::std::mem::align_of::<__kernel_sockaddr_storage>(),
|
pub const IPPROTO_IDP: ::std::os::raw::c_uint = 22;
|
||||||
8usize,
|
pub const IPPROTO_TP: ::std::os::raw::c_uint = 29;
|
||||||
concat!("Alignment of ", stringify!(__kernel_sockaddr_storage))
|
pub const IPPROTO_DCCP: ::std::os::raw::c_uint = 33;
|
||||||
);
|
pub const IPPROTO_IPV6: ::std::os::raw::c_uint = 41;
|
||||||
assert_eq!(
|
pub const IPPROTO_RSVP: ::std::os::raw::c_uint = 46;
|
||||||
unsafe { &(*(0 as *const __kernel_sockaddr_storage)).ss_family as *const _ as usize },
|
pub const IPPROTO_GRE: ::std::os::raw::c_uint = 47;
|
||||||
0usize,
|
pub const IPPROTO_ESP: ::std::os::raw::c_uint = 50;
|
||||||
concat!(
|
pub const IPPROTO_AH: ::std::os::raw::c_uint = 51;
|
||||||
"Alignment of field: ",
|
pub const IPPROTO_MTP: ::std::os::raw::c_uint = 92;
|
||||||
stringify!(__kernel_sockaddr_storage),
|
pub const IPPROTO_BEETPH: ::std::os::raw::c_uint = 94;
|
||||||
"::",
|
pub const IPPROTO_ENCAP: ::std::os::raw::c_uint = 98;
|
||||||
stringify!(ss_family)
|
pub const IPPROTO_PIM: ::std::os::raw::c_uint = 103;
|
||||||
)
|
pub const IPPROTO_COMP: ::std::os::raw::c_uint = 108;
|
||||||
);
|
pub const IPPROTO_SCTP: ::std::os::raw::c_uint = 132;
|
||||||
assert_eq!(
|
pub const IPPROTO_UDPLITE: ::std::os::raw::c_uint = 136;
|
||||||
unsafe { &(*(0 as *const __kernel_sockaddr_storage)).__data as *const _ as usize },
|
pub const IPPROTO_MPLS: ::std::os::raw::c_uint = 137;
|
||||||
2usize,
|
pub const IPPROTO_ETHERNET: ::std::os::raw::c_uint = 143;
|
||||||
concat!(
|
pub const IPPROTO_RAW: ::std::os::raw::c_uint = 255;
|
||||||
"Alignment of field: ",
|
pub const IPPROTO_MPTCP: ::std::os::raw::c_uint = 262;
|
||||||
stringify!(__kernel_sockaddr_storage),
|
pub const IPPROTO_MAX: ::std::os::raw::c_uint = 263;
|
||||||
"::",
|
|
||||||
stringify!(__data)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Default for __kernel_sockaddr_storage {
|
|
||||||
fn default() -> Self {
|
|
||||||
unsafe { ::std::mem::zeroed() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub const IPPROTO_IP: _bindgen_ty_1 = 0;
|
|
||||||
pub const IPPROTO_ICMP: _bindgen_ty_1 = 1;
|
|
||||||
pub const IPPROTO_IGMP: _bindgen_ty_1 = 2;
|
|
||||||
pub const IPPROTO_IPIP: _bindgen_ty_1 = 4;
|
|
||||||
pub const IPPROTO_TCP: _bindgen_ty_1 = 6;
|
|
||||||
pub const IPPROTO_EGP: _bindgen_ty_1 = 8;
|
|
||||||
pub const IPPROTO_PUP: _bindgen_ty_1 = 12;
|
|
||||||
pub const IPPROTO_UDP: _bindgen_ty_1 = 17;
|
|
||||||
pub const IPPROTO_IDP: _bindgen_ty_1 = 22;
|
|
||||||
pub const IPPROTO_TP: _bindgen_ty_1 = 29;
|
|
||||||
pub const IPPROTO_DCCP: _bindgen_ty_1 = 33;
|
|
||||||
pub const IPPROTO_IPV6: _bindgen_ty_1 = 41;
|
|
||||||
pub const IPPROTO_RSVP: _bindgen_ty_1 = 46;
|
|
||||||
pub const IPPROTO_GRE: _bindgen_ty_1 = 47;
|
|
||||||
pub const IPPROTO_ESP: _bindgen_ty_1 = 50;
|
|
||||||
pub const IPPROTO_AH: _bindgen_ty_1 = 51;
|
|
||||||
pub const IPPROTO_MTP: _bindgen_ty_1 = 92;
|
|
||||||
pub const IPPROTO_BEETPH: _bindgen_ty_1 = 94;
|
|
||||||
pub const IPPROTO_ENCAP: _bindgen_ty_1 = 98;
|
|
||||||
pub const IPPROTO_PIM: _bindgen_ty_1 = 103;
|
|
||||||
pub const IPPROTO_COMP: _bindgen_ty_1 = 108;
|
|
||||||
pub const IPPROTO_SCTP: _bindgen_ty_1 = 132;
|
|
||||||
pub const IPPROTO_UDPLITE: _bindgen_ty_1 = 136;
|
|
||||||
pub const IPPROTO_MPLS: _bindgen_ty_1 = 137;
|
|
||||||
pub const IPPROTO_RAW: _bindgen_ty_1 = 255;
|
|
||||||
pub const IPPROTO_MAX: _bindgen_ty_1 = 256;
|
|
||||||
pub type _bindgen_ty_1 = ::std::os::raw::c_uint;
|
pub type _bindgen_ty_1 = ::std::os::raw::c_uint;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct in_addr {
|
pub struct in_addr {
|
||||||
pub s_addr: __be32,
|
pub s_addr: __be32,
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_in_addr() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<in_addr>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Size of: ", stringify!(in_addr))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<in_addr>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Alignment of ", stringify!(in_addr))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const in_addr)).s_addr as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(in_addr),
|
|
||||||
"::",
|
|
||||||
stringify!(s_addr)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for in_addr {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct ip_mreq {
|
pub struct ip_mreq {
|
||||||
pub imr_multiaddr: in_addr,
|
pub imr_multiaddr: in_addr,
|
||||||
pub imr_interface: in_addr,
|
pub imr_interface: in_addr,
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_ip_mreq() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<ip_mreq>(),
|
|
||||||
8usize,
|
|
||||||
concat!("Size of: ", stringify!(ip_mreq))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<ip_mreq>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Alignment of ", stringify!(ip_mreq))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const ip_mreq)).imr_multiaddr as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(ip_mreq),
|
|
||||||
"::",
|
|
||||||
stringify!(imr_multiaddr)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const ip_mreq)).imr_interface as *const _ as usize },
|
|
||||||
4usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(ip_mreq),
|
|
||||||
"::",
|
|
||||||
stringify!(imr_interface)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for ip_mreq {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct ip_mreqn {
|
pub struct ip_mreqn {
|
||||||
pub imr_multiaddr: in_addr,
|
pub imr_multiaddr: in_addr,
|
||||||
pub imr_address: in_addr,
|
pub imr_address: in_addr,
|
||||||
pub imr_ifindex: ::std::os::raw::c_int,
|
pub imr_ifindex: ::std::os::raw::c_int,
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_ip_mreqn() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<ip_mreqn>(),
|
|
||||||
12usize,
|
|
||||||
concat!("Size of: ", stringify!(ip_mreqn))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<ip_mreqn>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Alignment of ", stringify!(ip_mreqn))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const ip_mreqn)).imr_multiaddr as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(ip_mreqn),
|
|
||||||
"::",
|
|
||||||
stringify!(imr_multiaddr)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const ip_mreqn)).imr_address as *const _ as usize },
|
|
||||||
4usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(ip_mreqn),
|
|
||||||
"::",
|
|
||||||
stringify!(imr_address)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const ip_mreqn)).imr_ifindex as *const _ as usize },
|
|
||||||
8usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(ip_mreqn),
|
|
||||||
"::",
|
|
||||||
stringify!(imr_ifindex)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for ip_mreqn {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct ip_mreq_source {
|
pub struct ip_mreq_source {
|
||||||
pub imr_multiaddr: __be32,
|
pub imr_multiaddr: __be32,
|
||||||
pub imr_interface: __be32,
|
pub imr_interface: __be32,
|
||||||
pub imr_sourceaddr: __be32,
|
pub imr_sourceaddr: __be32,
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_ip_mreq_source() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<ip_mreq_source>(),
|
|
||||||
12usize,
|
|
||||||
concat!("Size of: ", stringify!(ip_mreq_source))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<ip_mreq_source>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Alignment of ", stringify!(ip_mreq_source))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const ip_mreq_source)).imr_multiaddr as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(ip_mreq_source),
|
|
||||||
"::",
|
|
||||||
stringify!(imr_multiaddr)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const ip_mreq_source)).imr_interface as *const _ as usize },
|
|
||||||
4usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(ip_mreq_source),
|
|
||||||
"::",
|
|
||||||
stringify!(imr_interface)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const ip_mreq_source)).imr_sourceaddr as *const _ as usize },
|
|
||||||
8usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(ip_mreq_source),
|
|
||||||
"::",
|
|
||||||
stringify!(imr_sourceaddr)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for ip_mreq_source {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct ip_msfilter {
|
pub struct ip_msfilter {
|
||||||
pub imsf_multiaddr: __be32,
|
pub imsf_multiaddr: __be32,
|
||||||
pub imsf_interface: __be32,
|
pub imsf_interface: __be32,
|
||||||
@@ -479,172 +255,21 @@ pub struct ip_msfilter {
|
|||||||
pub imsf_numsrc: __u32,
|
pub imsf_numsrc: __u32,
|
||||||
pub imsf_slist: [__be32; 1usize],
|
pub imsf_slist: [__be32; 1usize],
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_ip_msfilter() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<ip_msfilter>(),
|
|
||||||
20usize,
|
|
||||||
concat!("Size of: ", stringify!(ip_msfilter))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<ip_msfilter>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Alignment of ", stringify!(ip_msfilter))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const ip_msfilter)).imsf_multiaddr as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(ip_msfilter),
|
|
||||||
"::",
|
|
||||||
stringify!(imsf_multiaddr)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const ip_msfilter)).imsf_interface as *const _ as usize },
|
|
||||||
4usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(ip_msfilter),
|
|
||||||
"::",
|
|
||||||
stringify!(imsf_interface)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const ip_msfilter)).imsf_fmode as *const _ as usize },
|
|
||||||
8usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(ip_msfilter),
|
|
||||||
"::",
|
|
||||||
stringify!(imsf_fmode)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const ip_msfilter)).imsf_numsrc as *const _ as usize },
|
|
||||||
12usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(ip_msfilter),
|
|
||||||
"::",
|
|
||||||
stringify!(imsf_numsrc)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const ip_msfilter)).imsf_slist as *const _ as usize },
|
|
||||||
16usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(ip_msfilter),
|
|
||||||
"::",
|
|
||||||
stringify!(imsf_slist)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for ip_msfilter {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
pub struct group_req {
|
pub struct group_req {
|
||||||
pub gr_interface: __u32,
|
pub gr_interface: __u32,
|
||||||
pub gr_group: __kernel_sockaddr_storage,
|
pub gr_group: __kernel_sockaddr_storage,
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_group_req() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<group_req>(),
|
|
||||||
136usize,
|
|
||||||
concat!("Size of: ", stringify!(group_req))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<group_req>(),
|
|
||||||
8usize,
|
|
||||||
concat!("Alignment of ", stringify!(group_req))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const group_req)).gr_interface as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(group_req),
|
|
||||||
"::",
|
|
||||||
stringify!(gr_interface)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const group_req)).gr_group as *const _ as usize },
|
|
||||||
8usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(group_req),
|
|
||||||
"::",
|
|
||||||
stringify!(gr_group)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Default for group_req {
|
|
||||||
fn default() -> Self {
|
|
||||||
unsafe { ::std::mem::zeroed() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
pub struct group_source_req {
|
pub struct group_source_req {
|
||||||
pub gsr_interface: __u32,
|
pub gsr_interface: __u32,
|
||||||
pub gsr_group: __kernel_sockaddr_storage,
|
pub gsr_group: __kernel_sockaddr_storage,
|
||||||
pub gsr_source: __kernel_sockaddr_storage,
|
pub gsr_source: __kernel_sockaddr_storage,
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_group_source_req() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<group_source_req>(),
|
|
||||||
264usize,
|
|
||||||
concat!("Size of: ", stringify!(group_source_req))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<group_source_req>(),
|
|
||||||
8usize,
|
|
||||||
concat!("Alignment of ", stringify!(group_source_req))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const group_source_req)).gsr_interface as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(group_source_req),
|
|
||||||
"::",
|
|
||||||
stringify!(gsr_interface)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const group_source_req)).gsr_group as *const _ as usize },
|
|
||||||
8usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(group_source_req),
|
|
||||||
"::",
|
|
||||||
stringify!(gsr_group)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const group_source_req)).gsr_source as *const _ as usize },
|
|
||||||
136usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(group_source_req),
|
|
||||||
"::",
|
|
||||||
stringify!(gsr_source)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Default for group_source_req {
|
|
||||||
fn default() -> Self {
|
|
||||||
unsafe { ::std::mem::zeroed() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
pub struct group_filter {
|
pub struct group_filter {
|
||||||
pub gf_interface: __u32,
|
pub gf_interface: __u32,
|
||||||
pub gf_group: __kernel_sockaddr_storage,
|
pub gf_group: __kernel_sockaddr_storage,
|
||||||
@@ -652,192 +277,18 @@ pub struct group_filter {
|
|||||||
pub gf_numsrc: __u32,
|
pub gf_numsrc: __u32,
|
||||||
pub gf_slist: [__kernel_sockaddr_storage; 1usize],
|
pub gf_slist: [__kernel_sockaddr_storage; 1usize],
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_group_filter() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<group_filter>(),
|
|
||||||
272usize,
|
|
||||||
concat!("Size of: ", stringify!(group_filter))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<group_filter>(),
|
|
||||||
8usize,
|
|
||||||
concat!("Alignment of ", stringify!(group_filter))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const group_filter)).gf_interface as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(group_filter),
|
|
||||||
"::",
|
|
||||||
stringify!(gf_interface)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const group_filter)).gf_group as *const _ as usize },
|
|
||||||
8usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(group_filter),
|
|
||||||
"::",
|
|
||||||
stringify!(gf_group)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const group_filter)).gf_fmode as *const _ as usize },
|
|
||||||
136usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(group_filter),
|
|
||||||
"::",
|
|
||||||
stringify!(gf_fmode)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const group_filter)).gf_numsrc as *const _ as usize },
|
|
||||||
140usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(group_filter),
|
|
||||||
"::",
|
|
||||||
stringify!(gf_numsrc)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const group_filter)).gf_slist as *const _ as usize },
|
|
||||||
144usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(group_filter),
|
|
||||||
"::",
|
|
||||||
stringify!(gf_slist)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Default for group_filter {
|
|
||||||
fn default() -> Self {
|
|
||||||
unsafe { ::std::mem::zeroed() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct in_pktinfo {
|
pub struct in_pktinfo {
|
||||||
pub ipi_ifindex: ::std::os::raw::c_int,
|
pub ipi_ifindex: ::std::os::raw::c_int,
|
||||||
pub ipi_spec_dst: in_addr,
|
pub ipi_spec_dst: in_addr,
|
||||||
pub ipi_addr: in_addr,
|
pub ipi_addr: in_addr,
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_in_pktinfo() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<in_pktinfo>(),
|
|
||||||
12usize,
|
|
||||||
concat!("Size of: ", stringify!(in_pktinfo))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<in_pktinfo>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Alignment of ", stringify!(in_pktinfo))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const in_pktinfo)).ipi_ifindex as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(in_pktinfo),
|
|
||||||
"::",
|
|
||||||
stringify!(ipi_ifindex)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const in_pktinfo)).ipi_spec_dst as *const _ as usize },
|
|
||||||
4usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(in_pktinfo),
|
|
||||||
"::",
|
|
||||||
stringify!(ipi_spec_dst)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const in_pktinfo)).ipi_addr as *const _ as usize },
|
|
||||||
8usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(in_pktinfo),
|
|
||||||
"::",
|
|
||||||
stringify!(ipi_addr)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for in_pktinfo {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct sockaddr_in {
|
pub struct sockaddr_in {
|
||||||
pub sin_family: __kernel_sa_family_t,
|
pub sin_family: __kernel_sa_family_t,
|
||||||
pub sin_port: __be16,
|
pub sin_port: __be16,
|
||||||
pub sin_addr: in_addr,
|
pub sin_addr: in_addr,
|
||||||
pub __pad: [::std::os::raw::c_uchar; 8usize],
|
pub __pad: [::std::os::raw::c_uchar; 8usize],
|
||||||
}
|
}
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_sockaddr_in() {
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<sockaddr_in>(),
|
|
||||||
16usize,
|
|
||||||
concat!("Size of: ", stringify!(sockaddr_in))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<sockaddr_in>(),
|
|
||||||
4usize,
|
|
||||||
concat!("Alignment of ", stringify!(sockaddr_in))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const sockaddr_in)).sin_family as *const _ as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(sockaddr_in),
|
|
||||||
"::",
|
|
||||||
stringify!(sin_family)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const sockaddr_in)).sin_port as *const _ as usize },
|
|
||||||
2usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(sockaddr_in),
|
|
||||||
"::",
|
|
||||||
stringify!(sin_port)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const sockaddr_in)).sin_addr as *const _ as usize },
|
|
||||||
4usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(sockaddr_in),
|
|
||||||
"::",
|
|
||||||
stringify!(sin_addr)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { &(*(0 as *const sockaddr_in)).__pad as *const _ as usize },
|
|
||||||
8usize,
|
|
||||||
concat!(
|
|
||||||
"Alignment of field: ",
|
|
||||||
stringify!(sockaddr_in),
|
|
||||||
"::",
|
|
||||||
stringify!(__pad)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
impl Clone for sockaddr_in {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,89 +1,95 @@
|
|||||||
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
// Copyright © 2021 Intel Corporation
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
//
|
||||||
// found in the THIRD-PARTY file.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
/* automatically generated by rust-bindgen */
|
// bindgen /usr/include/linux/sockios.h --no-layout-tests
|
||||||
|
|
||||||
pub const FIOSETOWN: ::std::os::raw::c_uint = 35073;
|
/* automatically generated by rust-bindgen 0.58.1 */
|
||||||
pub const SIOCSPGRP: ::std::os::raw::c_uint = 35074;
|
|
||||||
pub const FIOGETOWN: ::std::os::raw::c_uint = 35075;
|
pub const __BITS_PER_LONG: u32 = 64;
|
||||||
pub const SIOCGPGRP: ::std::os::raw::c_uint = 35076;
|
pub const FIOSETOWN: u32 = 35073;
|
||||||
pub const SIOCATMARK: ::std::os::raw::c_uint = 35077;
|
pub const SIOCSPGRP: u32 = 35074;
|
||||||
pub const SIOCGSTAMP: ::std::os::raw::c_uint = 35078;
|
pub const FIOGETOWN: u32 = 35075;
|
||||||
pub const SIOCGSTAMPNS: ::std::os::raw::c_uint = 35079;
|
pub const SIOCGPGRP: u32 = 35076;
|
||||||
pub const SOCK_IOC_TYPE: ::std::os::raw::c_uint = 137;
|
pub const SIOCATMARK: u32 = 35077;
|
||||||
pub const SIOCADDRT: ::std::os::raw::c_uint = 35083;
|
pub const SIOCGSTAMP_OLD: u32 = 35078;
|
||||||
pub const SIOCDELRT: ::std::os::raw::c_uint = 35084;
|
pub const SIOCGSTAMPNS_OLD: u32 = 35079;
|
||||||
pub const SIOCRTMSG: ::std::os::raw::c_uint = 35085;
|
pub const SOCK_IOC_TYPE: u32 = 137;
|
||||||
pub const SIOCGIFNAME: ::std::os::raw::c_uint = 35088;
|
pub const SIOCGSTAMP: u32 = 35078;
|
||||||
pub const SIOCSIFLINK: ::std::os::raw::c_uint = 35089;
|
pub const SIOCGSTAMPNS: u32 = 35079;
|
||||||
pub const SIOCGIFCONF: ::std::os::raw::c_uint = 35090;
|
pub const SIOCADDRT: u32 = 35083;
|
||||||
pub const SIOCGIFFLAGS: ::std::os::raw::c_uint = 35091;
|
pub const SIOCDELRT: u32 = 35084;
|
||||||
pub const SIOCSIFFLAGS: ::std::os::raw::c_uint = 35092;
|
pub const SIOCRTMSG: u32 = 35085;
|
||||||
pub const SIOCGIFADDR: ::std::os::raw::c_uint = 35093;
|
pub const SIOCGIFNAME: u32 = 35088;
|
||||||
pub const SIOCSIFADDR: ::std::os::raw::c_uint = 35094;
|
pub const SIOCSIFLINK: u32 = 35089;
|
||||||
pub const SIOCGIFDSTADDR: ::std::os::raw::c_uint = 35095;
|
pub const SIOCGIFCONF: u32 = 35090;
|
||||||
pub const SIOCSIFDSTADDR: ::std::os::raw::c_uint = 35096;
|
pub const SIOCGIFFLAGS: u32 = 35091;
|
||||||
pub const SIOCGIFBRDADDR: ::std::os::raw::c_uint = 35097;
|
pub const SIOCSIFFLAGS: u32 = 35092;
|
||||||
pub const SIOCSIFBRDADDR: ::std::os::raw::c_uint = 35098;
|
pub const SIOCGIFADDR: u32 = 35093;
|
||||||
pub const SIOCGIFNETMASK: ::std::os::raw::c_uint = 35099;
|
pub const SIOCSIFADDR: u32 = 35094;
|
||||||
pub const SIOCSIFNETMASK: ::std::os::raw::c_uint = 35100;
|
pub const SIOCGIFDSTADDR: u32 = 35095;
|
||||||
pub const SIOCGIFMETRIC: ::std::os::raw::c_uint = 35101;
|
pub const SIOCSIFDSTADDR: u32 = 35096;
|
||||||
pub const SIOCSIFMETRIC: ::std::os::raw::c_uint = 35102;
|
pub const SIOCGIFBRDADDR: u32 = 35097;
|
||||||
pub const SIOCGIFMEM: ::std::os::raw::c_uint = 35103;
|
pub const SIOCSIFBRDADDR: u32 = 35098;
|
||||||
pub const SIOCSIFMEM: ::std::os::raw::c_uint = 35104;
|
pub const SIOCGIFNETMASK: u32 = 35099;
|
||||||
pub const SIOCGIFMTU: ::std::os::raw::c_uint = 35105;
|
pub const SIOCSIFNETMASK: u32 = 35100;
|
||||||
pub const SIOCSIFMTU: ::std::os::raw::c_uint = 35106;
|
pub const SIOCGIFMETRIC: u32 = 35101;
|
||||||
pub const SIOCSIFNAME: ::std::os::raw::c_uint = 35107;
|
pub const SIOCSIFMETRIC: u32 = 35102;
|
||||||
pub const SIOCSIFHWADDR: ::std::os::raw::c_uint = 35108;
|
pub const SIOCGIFMEM: u32 = 35103;
|
||||||
pub const SIOCGIFENCAP: ::std::os::raw::c_uint = 35109;
|
pub const SIOCSIFMEM: u32 = 35104;
|
||||||
pub const SIOCSIFENCAP: ::std::os::raw::c_uint = 35110;
|
pub const SIOCGIFMTU: u32 = 35105;
|
||||||
pub const SIOCGIFHWADDR: ::std::os::raw::c_uint = 35111;
|
pub const SIOCSIFMTU: u32 = 35106;
|
||||||
pub const SIOCGIFSLAVE: ::std::os::raw::c_uint = 35113;
|
pub const SIOCSIFNAME: u32 = 35107;
|
||||||
pub const SIOCSIFSLAVE: ::std::os::raw::c_uint = 35120;
|
pub const SIOCSIFHWADDR: u32 = 35108;
|
||||||
pub const SIOCADDMULTI: ::std::os::raw::c_uint = 35121;
|
pub const SIOCGIFENCAP: u32 = 35109;
|
||||||
pub const SIOCDELMULTI: ::std::os::raw::c_uint = 35122;
|
pub const SIOCSIFENCAP: u32 = 35110;
|
||||||
pub const SIOCGIFINDEX: ::std::os::raw::c_uint = 35123;
|
pub const SIOCGIFHWADDR: u32 = 35111;
|
||||||
pub const SIOGIFINDEX: ::std::os::raw::c_uint = 35123;
|
pub const SIOCGIFSLAVE: u32 = 35113;
|
||||||
pub const SIOCSIFPFLAGS: ::std::os::raw::c_uint = 35124;
|
pub const SIOCSIFSLAVE: u32 = 35120;
|
||||||
pub const SIOCGIFPFLAGS: ::std::os::raw::c_uint = 35125;
|
pub const SIOCADDMULTI: u32 = 35121;
|
||||||
pub const SIOCDIFADDR: ::std::os::raw::c_uint = 35126;
|
pub const SIOCDELMULTI: u32 = 35122;
|
||||||
pub const SIOCSIFHWBROADCAST: ::std::os::raw::c_uint = 35127;
|
pub const SIOCGIFINDEX: u32 = 35123;
|
||||||
pub const SIOCGIFCOUNT: ::std::os::raw::c_uint = 35128;
|
pub const SIOGIFINDEX: u32 = 35123;
|
||||||
pub const SIOCGIFBR: ::std::os::raw::c_uint = 35136;
|
pub const SIOCSIFPFLAGS: u32 = 35124;
|
||||||
pub const SIOCSIFBR: ::std::os::raw::c_uint = 35137;
|
pub const SIOCGIFPFLAGS: u32 = 35125;
|
||||||
pub const SIOCGIFTXQLEN: ::std::os::raw::c_uint = 35138;
|
pub const SIOCDIFADDR: u32 = 35126;
|
||||||
pub const SIOCSIFTXQLEN: ::std::os::raw::c_uint = 35139;
|
pub const SIOCSIFHWBROADCAST: u32 = 35127;
|
||||||
pub const SIOCETHTOOL: ::std::os::raw::c_uint = 35142;
|
pub const SIOCGIFCOUNT: u32 = 35128;
|
||||||
pub const SIOCGMIIPHY: ::std::os::raw::c_uint = 35143;
|
pub const SIOCGIFBR: u32 = 35136;
|
||||||
pub const SIOCGMIIREG: ::std::os::raw::c_uint = 35144;
|
pub const SIOCSIFBR: u32 = 35137;
|
||||||
pub const SIOCSMIIREG: ::std::os::raw::c_uint = 35145;
|
pub const SIOCGIFTXQLEN: u32 = 35138;
|
||||||
pub const SIOCWANDEV: ::std::os::raw::c_uint = 35146;
|
pub const SIOCSIFTXQLEN: u32 = 35139;
|
||||||
pub const SIOCOUTQNSD: ::std::os::raw::c_uint = 35147;
|
pub const SIOCETHTOOL: u32 = 35142;
|
||||||
pub const SIOCGSKNS: ::std::os::raw::c_uint = 35148;
|
pub const SIOCGMIIPHY: u32 = 35143;
|
||||||
pub const SIOCDARP: ::std::os::raw::c_uint = 35155;
|
pub const SIOCGMIIREG: u32 = 35144;
|
||||||
pub const SIOCGARP: ::std::os::raw::c_uint = 35156;
|
pub const SIOCSMIIREG: u32 = 35145;
|
||||||
pub const SIOCSARP: ::std::os::raw::c_uint = 35157;
|
pub const SIOCWANDEV: u32 = 35146;
|
||||||
pub const SIOCDRARP: ::std::os::raw::c_uint = 35168;
|
pub const SIOCOUTQNSD: u32 = 35147;
|
||||||
pub const SIOCGRARP: ::std::os::raw::c_uint = 35169;
|
pub const SIOCGSKNS: u32 = 35148;
|
||||||
pub const SIOCSRARP: ::std::os::raw::c_uint = 35170;
|
pub const SIOCDARP: u32 = 35155;
|
||||||
pub const SIOCGIFMAP: ::std::os::raw::c_uint = 35184;
|
pub const SIOCGARP: u32 = 35156;
|
||||||
pub const SIOCSIFMAP: ::std::os::raw::c_uint = 35185;
|
pub const SIOCSARP: u32 = 35157;
|
||||||
pub const SIOCADDDLCI: ::std::os::raw::c_uint = 35200;
|
pub const SIOCDRARP: u32 = 35168;
|
||||||
pub const SIOCDELDLCI: ::std::os::raw::c_uint = 35201;
|
pub const SIOCGRARP: u32 = 35169;
|
||||||
pub const SIOCGIFVLAN: ::std::os::raw::c_uint = 35202;
|
pub const SIOCSRARP: u32 = 35170;
|
||||||
pub const SIOCSIFVLAN: ::std::os::raw::c_uint = 35203;
|
pub const SIOCGIFMAP: u32 = 35184;
|
||||||
pub const SIOCBONDENSLAVE: ::std::os::raw::c_uint = 35216;
|
pub const SIOCSIFMAP: u32 = 35185;
|
||||||
pub const SIOCBONDRELEASE: ::std::os::raw::c_uint = 35217;
|
pub const SIOCADDDLCI: u32 = 35200;
|
||||||
pub const SIOCBONDSETHWADDR: ::std::os::raw::c_uint = 35218;
|
pub const SIOCDELDLCI: u32 = 35201;
|
||||||
pub const SIOCBONDSLAVEINFOQUERY: ::std::os::raw::c_uint = 35219;
|
pub const SIOCGIFVLAN: u32 = 35202;
|
||||||
pub const SIOCBONDINFOQUERY: ::std::os::raw::c_uint = 35220;
|
pub const SIOCSIFVLAN: u32 = 35203;
|
||||||
pub const SIOCBONDCHANGEACTIVE: ::std::os::raw::c_uint = 35221;
|
pub const SIOCBONDENSLAVE: u32 = 35216;
|
||||||
pub const SIOCBRADDBR: ::std::os::raw::c_uint = 35232;
|
pub const SIOCBONDRELEASE: u32 = 35217;
|
||||||
pub const SIOCBRDELBR: ::std::os::raw::c_uint = 35233;
|
pub const SIOCBONDSETHWADDR: u32 = 35218;
|
||||||
pub const SIOCBRADDIF: ::std::os::raw::c_uint = 35234;
|
pub const SIOCBONDSLAVEINFOQUERY: u32 = 35219;
|
||||||
pub const SIOCBRDELIF: ::std::os::raw::c_uint = 35235;
|
pub const SIOCBONDINFOQUERY: u32 = 35220;
|
||||||
pub const SIOCSHWTSTAMP: ::std::os::raw::c_uint = 35248;
|
pub const SIOCBONDCHANGEACTIVE: u32 = 35221;
|
||||||
pub const SIOCGHWTSTAMP: ::std::os::raw::c_uint = 35249;
|
pub const SIOCBRADDBR: u32 = 35232;
|
||||||
pub const SIOCDEVPRIVATE: ::std::os::raw::c_uint = 35312;
|
pub const SIOCBRDELBR: u32 = 35233;
|
||||||
pub const SIOCPROTOPRIVATE: ::std::os::raw::c_uint = 35296;
|
pub const SIOCBRADDIF: u32 = 35234;
|
||||||
|
pub const SIOCBRDELIF: u32 = 35235;
|
||||||
|
pub const SIOCSHWTSTAMP: u32 = 35248;
|
||||||
|
pub const SIOCGHWTSTAMP: u32 = 35249;
|
||||||
|
pub const SIOCDEVPRIVATE: u32 = 35312;
|
||||||
|
pub const SIOCPROTOPRIVATE: u32 = 35296;
|
||||||
|
|||||||
@@ -2,20 +2,23 @@
|
|||||||
name = "net_util"
|
name = "net_util"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["The Chromium OS Authors"]
|
authors = ["The Chromium OS Authors"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
epoll = ">=4.0.1"
|
epoll = ">=4.0.1"
|
||||||
libc = "0.2.94"
|
libc = "0.2.96"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
net_gen = { path = "../net_gen" }
|
net_gen = { path = "../net_gen" }
|
||||||
rate_limiter = { path = "../rate_limiter" }
|
rate_limiter = { path = "../rate_limiter" }
|
||||||
serde = "1.0.125"
|
serde = "1.0.126"
|
||||||
|
versionize = "0.1.6"
|
||||||
|
versionize_derive = "0.1.4"
|
||||||
virtio-bindings = "0.1.0"
|
virtio-bindings = "0.1.0"
|
||||||
vm-memory = { version = "0.5.0", features = ["backend-mmap", "backend-atomic"] }
|
vm-memory = { version = "0.5.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
vmm-sys-util = ">=0.3.1"
|
vmm-sys-util = ">=0.3.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
lazy_static = "1.3.0"
|
lazy_static = "1.3.0"
|
||||||
pnet = "0.27.2"
|
pnet = "0.28.0"
|
||||||
serde_json = "1.0.64"
|
serde_json = "1.0.64"
|
||||||
|
|||||||
141
net_util/src/ctrl_queue.rs
Normal file
141
net_util/src/ctrl_queue.rs
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
// Copyright (c) 2021 Intel Corporation. All rights reserved.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||||
|
|
||||||
|
use crate::GuestMemoryMmap;
|
||||||
|
use crate::Tap;
|
||||||
|
use libc::c_uint;
|
||||||
|
use virtio_bindings::bindings::virtio_net::{
|
||||||
|
VIRTIO_NET_CTRL_GUEST_OFFLOADS, VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET, VIRTIO_NET_CTRL_MQ,
|
||||||
|
VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN,
|
||||||
|
VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, VIRTIO_NET_ERR, VIRTIO_NET_F_GUEST_CSUM,
|
||||||
|
VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
|
||||||
|
VIRTIO_NET_F_GUEST_UFO, VIRTIO_NET_OK,
|
||||||
|
};
|
||||||
|
use vm_memory::{ByteValued, Bytes, GuestMemoryError};
|
||||||
|
use vm_virtio::Queue;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
/// Read queue failed.
|
||||||
|
GuestMemory(GuestMemoryError),
|
||||||
|
/// No queue pairs number.
|
||||||
|
NoQueuePairsDescriptor,
|
||||||
|
/// No status descriptor
|
||||||
|
NoStatusDescriptor,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
pub struct ControlHeader {
|
||||||
|
pub class: u8,
|
||||||
|
pub cmd: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl ByteValued for ControlHeader {}
|
||||||
|
|
||||||
|
pub struct CtrlQueue {
|
||||||
|
pub taps: Vec<Tap>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CtrlQueue {
|
||||||
|
pub fn new(taps: Vec<Tap>) -> Self {
|
||||||
|
CtrlQueue { taps }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process(&mut self, mem: &GuestMemoryMmap, queue: &mut Queue) -> Result<bool> {
|
||||||
|
let mut used_desc_heads = Vec::new();
|
||||||
|
for avail_desc in queue.iter(&mem) {
|
||||||
|
let ctrl_hdr: ControlHeader =
|
||||||
|
mem.read_obj(avail_desc.addr).map_err(Error::GuestMemory)?;
|
||||||
|
let data_desc = avail_desc
|
||||||
|
.next_descriptor()
|
||||||
|
.ok_or(Error::NoQueuePairsDescriptor)?;
|
||||||
|
let status_desc = data_desc
|
||||||
|
.next_descriptor()
|
||||||
|
.ok_or(Error::NoStatusDescriptor)?;
|
||||||
|
|
||||||
|
let ok = match u32::from(ctrl_hdr.class) {
|
||||||
|
VIRTIO_NET_CTRL_MQ => {
|
||||||
|
let queue_pairs = mem
|
||||||
|
.read_obj::<u16>(data_desc.addr)
|
||||||
|
.map_err(Error::GuestMemory)?;
|
||||||
|
if u32::from(ctrl_hdr.cmd) != VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET {
|
||||||
|
warn!("Unsupported command: {}", ctrl_hdr.cmd);
|
||||||
|
false
|
||||||
|
} else if (queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN as u16)
|
||||||
|
|| (queue_pairs > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX as u16)
|
||||||
|
{
|
||||||
|
warn!("Number of MQ pairs out of range: {}", queue_pairs);
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
info!("Number of MQ pairs requested: {}", queue_pairs);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VIRTIO_NET_CTRL_GUEST_OFFLOADS => {
|
||||||
|
let features = mem
|
||||||
|
.read_obj::<u64>(data_desc.addr)
|
||||||
|
.map_err(Error::GuestMemory)?;
|
||||||
|
if u32::from(ctrl_hdr.cmd) != VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET {
|
||||||
|
warn!("Unsupported command: {}", ctrl_hdr.cmd);
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
let mut ok = true;
|
||||||
|
for tap in self.taps.iter_mut() {
|
||||||
|
info!("Reprogramming tap offload with features: {}", features);
|
||||||
|
tap.set_offload(virtio_features_to_tap_offload(features))
|
||||||
|
.map_err(|e| {
|
||||||
|
error!("Error programming tap offload: {:?}", e);
|
||||||
|
ok = false
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
ok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
warn!("Unsupported command {:?}", ctrl_hdr);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mem.write_obj(
|
||||||
|
if ok { VIRTIO_NET_OK } else { VIRTIO_NET_ERR } as u8,
|
||||||
|
status_desc.addr,
|
||||||
|
)
|
||||||
|
.map_err(Error::GuestMemory)?;
|
||||||
|
used_desc_heads.push((avail_desc.index, avail_desc.len));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (desc_index, len) in used_desc_heads.iter() {
|
||||||
|
queue.add_used(&mem, *desc_index, *len);
|
||||||
|
queue.update_avail_event(&mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(!used_desc_heads.is_empty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn virtio_features_to_tap_offload(features: u64) -> c_uint {
|
||||||
|
let mut tap_offloads: c_uint = 0;
|
||||||
|
if features & (1 << VIRTIO_NET_F_GUEST_CSUM) != 0 {
|
||||||
|
tap_offloads |= net_gen::TUN_F_CSUM;
|
||||||
|
}
|
||||||
|
if features & (1 << VIRTIO_NET_F_GUEST_TSO4) != 0 {
|
||||||
|
tap_offloads |= net_gen::TUN_F_TSO4;
|
||||||
|
}
|
||||||
|
if features & (1 << VIRTIO_NET_F_GUEST_TSO6) != 0 {
|
||||||
|
tap_offloads |= net_gen::TUN_F_TSO6;
|
||||||
|
}
|
||||||
|
if features & (1 << VIRTIO_NET_F_GUEST_ECN) != 0 {
|
||||||
|
tap_offloads |= net_gen::TUN_F_TSO_ECN;
|
||||||
|
}
|
||||||
|
if features & (1 << VIRTIO_NET_F_GUEST_UFO) != 0 {
|
||||||
|
tap_offloads |= net_gen::TUN_F_UFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
tap_offloads
|
||||||
|
}
|
||||||
@@ -10,26 +10,31 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
extern crate libc;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
extern crate net_gen;
|
|
||||||
extern crate rate_limiter;
|
|
||||||
extern crate serde;
|
|
||||||
extern crate virtio_bindings;
|
|
||||||
extern crate vm_memory;
|
|
||||||
extern crate vm_virtio;
|
|
||||||
extern crate vmm_sys_util;
|
|
||||||
|
|
||||||
|
mod ctrl_queue;
|
||||||
mod mac;
|
mod mac;
|
||||||
mod open_tap;
|
mod open_tap;
|
||||||
mod queue_pair;
|
mod queue_pair;
|
||||||
mod tap;
|
mod tap;
|
||||||
|
|
||||||
use std::io::Error as IoError;
|
use std::io::Error as IoError;
|
||||||
|
use std::os::raw::c_uint;
|
||||||
use std::os::unix::io::{FromRawFd, RawFd};
|
use std::os::unix::io::{FromRawFd, RawFd};
|
||||||
use std::{io, mem, net};
|
use std::{io, mem, net};
|
||||||
|
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||||
|
use versionize_derive::Versionize;
|
||||||
|
use virtio_bindings::bindings::virtio_net::{
|
||||||
|
virtio_net_hdr_v1, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN,
|
||||||
|
VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_TSO4,
|
||||||
|
VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_GUEST_UFO, VIRTIO_NET_F_MAC, VIRTIO_NET_F_MQ,
|
||||||
|
};
|
||||||
|
use vm_memory::{bitmap::AtomicBitmap, ByteValued};
|
||||||
|
|
||||||
|
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
|
||||||
|
|
||||||
|
pub use ctrl_queue::{CtrlQueue, Error as CtrlQueueError};
|
||||||
pub use mac::{MacAddr, MAC_ADDR_LEN};
|
pub use mac::{MacAddr, MAC_ADDR_LEN};
|
||||||
pub use open_tap::{open_tap, Error as OpenTapError};
|
pub use open_tap::{open_tap, Error as OpenTapError};
|
||||||
pub use queue_pair::{NetCounters, NetQueuePair, NetQueuePairError, RxVirtio, TxVirtio};
|
pub use queue_pair::{NetCounters, NetQueuePair, NetQueuePairError, RxVirtio, TxVirtio};
|
||||||
@@ -43,6 +48,20 @@ pub enum Error {
|
|||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Copy, Clone, Debug, Default, Versionize)]
|
||||||
|
pub struct VirtioNetConfig {
|
||||||
|
pub mac: [u8; 6],
|
||||||
|
pub status: u16,
|
||||||
|
pub max_virtqueue_pairs: u16,
|
||||||
|
pub mtu: u16,
|
||||||
|
pub speed: u32,
|
||||||
|
pub duplex: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Safe because it only has data and has no implicit padding.
|
||||||
|
unsafe impl ByteValued for VirtioNetConfig {}
|
||||||
|
|
||||||
/// Create a sockaddr_in from an IPv4 address, and expose it as
|
/// Create a sockaddr_in from an IPv4 address, and expose it as
|
||||||
/// an opaque sockaddr suitable for usage by socket ioctls.
|
/// an opaque sockaddr suitable for usage by socket ioctls.
|
||||||
fn create_sockaddr(ip_addr: net::Ipv4Addr) -> net_gen::sockaddr {
|
fn create_sockaddr(ip_addr: net::Ipv4Addr) -> net_gen::sockaddr {
|
||||||
@@ -70,7 +89,6 @@ fn create_socket() -> Result<net::UdpSocket> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn vnet_hdr_len() -> usize {
|
fn vnet_hdr_len() -> usize {
|
||||||
use virtio_bindings::bindings::virtio_net::virtio_net_hdr_v1;
|
|
||||||
std::mem::size_of::<virtio_net_hdr_v1>()
|
std::mem::size_of::<virtio_net_hdr_v1>()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +120,53 @@ pub fn unregister_listener(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn build_net_config_space(
|
||||||
|
mut config: &mut VirtioNetConfig,
|
||||||
|
mac: MacAddr,
|
||||||
|
num_queues: usize,
|
||||||
|
avail_features: &mut u64,
|
||||||
|
) {
|
||||||
|
config.mac.copy_from_slice(mac.get_bytes());
|
||||||
|
*avail_features |= 1 << VIRTIO_NET_F_MAC;
|
||||||
|
|
||||||
|
build_net_config_space_with_mq(&mut config, num_queues, avail_features);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_net_config_space_with_mq(
|
||||||
|
config: &mut VirtioNetConfig,
|
||||||
|
num_queues: usize,
|
||||||
|
avail_features: &mut u64,
|
||||||
|
) {
|
||||||
|
let num_queue_pairs = (num_queues / 2) as u16;
|
||||||
|
if (num_queue_pairs >= VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN as u16)
|
||||||
|
&& (num_queue_pairs <= VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX as u16)
|
||||||
|
{
|
||||||
|
config.max_virtqueue_pairs = num_queue_pairs;
|
||||||
|
*avail_features |= 1 << VIRTIO_NET_F_MQ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn virtio_features_to_tap_offload(features: u64) -> c_uint {
|
||||||
|
let mut tap_offloads: c_uint = 0;
|
||||||
|
if features & (1 << VIRTIO_NET_F_GUEST_CSUM) != 0 {
|
||||||
|
tap_offloads |= net_gen::TUN_F_CSUM;
|
||||||
|
}
|
||||||
|
if features & (1 << VIRTIO_NET_F_GUEST_TSO4) != 0 {
|
||||||
|
tap_offloads |= net_gen::TUN_F_TSO4;
|
||||||
|
}
|
||||||
|
if features & (1 << VIRTIO_NET_F_GUEST_TSO6) != 0 {
|
||||||
|
tap_offloads |= net_gen::TUN_F_TSO6;
|
||||||
|
}
|
||||||
|
if features & (1 << VIRTIO_NET_F_GUEST_ECN) != 0 {
|
||||||
|
tap_offloads |= net_gen::TUN_F_TSO_ECN;
|
||||||
|
}
|
||||||
|
if features & (1 << VIRTIO_NET_F_GUEST_UFO) != 0 {
|
||||||
|
tap_offloads |= net_gen::TUN_F_UFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
tap_offloads
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -152,8 +152,6 @@ impl FromStr for MacAddr {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
extern crate serde_json;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ pub enum Error {
|
|||||||
TapSetMac(TapError),
|
TapSetMac(TapError),
|
||||||
/// Getting MAC address failed
|
/// Getting MAC address failed
|
||||||
TapGetMac(TapError),
|
TapGetMac(TapError),
|
||||||
/// Setting tap interface offload flags failed.
|
|
||||||
TapSetOffload(TapError),
|
|
||||||
/// Setting vnet header size failed.
|
/// Setting vnet header size failed.
|
||||||
TapSetVnetHdrSize(TapError),
|
TapSetVnetHdrSize(TapError),
|
||||||
/// Enabling tap interface failed.
|
/// Enabling tap interface failed.
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||||
|
|
||||||
use super::{unregister_listener, vnet_hdr_len, Tap};
|
use super::{unregister_listener, vnet_hdr_len, Tap};
|
||||||
|
use crate::GuestMemoryMmap;
|
||||||
use rate_limiter::{RateLimiter, TokenType};
|
use rate_limiter::{RateLimiter, TokenType};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::num::Wrapping;
|
use std::num::Wrapping;
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
use std::sync::atomic::{AtomicU64, Ordering};
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vm_memory::{Bytes, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, GuestMemoryMmap};
|
use vm_memory::{Bytes, GuestAddressSpace, GuestMemory, GuestMemoryAtomic};
|
||||||
use vm_virtio::Queue;
|
use vm_virtio::Queue;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|||||||
@@ -6,8 +6,7 @@
|
|||||||
// found in the THIRD-PARTY file.
|
// found in the THIRD-PARTY file.
|
||||||
|
|
||||||
use super::{create_sockaddr, create_socket, vnet_hdr_len, Error as NetUtilError, MacAddr};
|
use super::{create_sockaddr, create_socket, vnet_hdr_len, Error as NetUtilError, MacAddr};
|
||||||
use mac::MAC_ADDR_LEN;
|
use crate::mac::MAC_ADDR_LEN;
|
||||||
use net_gen;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Error as IoError, Read, Result as IoResult, Write};
|
use std::io::{Error as IoError, Read, Result as IoResult, Write};
|
||||||
use std::net;
|
use std::net;
|
||||||
@@ -121,13 +120,12 @@ impl Tap {
|
|||||||
let mut ifreq: net_gen::ifreq = Default::default();
|
let mut ifreq: net_gen::ifreq = Default::default();
|
||||||
unsafe {
|
unsafe {
|
||||||
let ifrn_name = ifreq.ifr_ifrn.ifrn_name.as_mut();
|
let ifrn_name = ifreq.ifr_ifrn.ifrn_name.as_mut();
|
||||||
let ifru_flags = ifreq.ifr_ifru.ifru_flags.as_mut();
|
|
||||||
let name_slice = &mut ifrn_name[..terminated_if_name.len()];
|
let name_slice = &mut ifrn_name[..terminated_if_name.len()];
|
||||||
name_slice.copy_from_slice(terminated_if_name.as_slice());
|
name_slice.copy_from_slice(terminated_if_name.as_slice());
|
||||||
*ifru_flags =
|
ifreq.ifr_ifru.ifru_flags =
|
||||||
(net_gen::IFF_TAP | net_gen::IFF_NO_PI | net_gen::IFF_VNET_HDR) as c_short;
|
(net_gen::IFF_TAP | net_gen::IFF_NO_PI | net_gen::IFF_VNET_HDR) as c_short;
|
||||||
if num_queue_pairs > 1 {
|
if num_queue_pairs > 1 {
|
||||||
*ifru_flags |= net_gen::IFF_MULTI_QUEUE as c_short;
|
ifreq.ifr_ifru.ifru_flags |= net_gen::IFF_MULTI_QUEUE as c_short;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,8 +136,7 @@ impl Tap {
|
|||||||
return Err(Error::ConfigureTap(IoError::last_os_error()));
|
return Err(Error::ConfigureTap(IoError::last_os_error()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let if_name_temp = unsafe { *ifreq.ifr_ifrn.ifrn_name.as_ref() };
|
let mut if_name = unsafe { ifreq.ifr_ifrn.ifrn_name }.to_vec();
|
||||||
let mut if_name = if_name_temp.to_vec();
|
|
||||||
if_name.truncate(terminated_if_name.len() - 1);
|
if_name.truncate(terminated_if_name.len() - 1);
|
||||||
// Safe since only the name is accessed, and it's cloned out.
|
// Safe since only the name is accessed, and it's cloned out.
|
||||||
Ok(Tap {
|
Ok(Tap {
|
||||||
@@ -173,16 +170,16 @@ impl Tap {
|
|||||||
if ret < 0 {
|
if ret < 0 {
|
||||||
return Err(Error::IoctlError(IoError::last_os_error()));
|
return Err(Error::IoctlError(IoError::last_os_error()));
|
||||||
}
|
}
|
||||||
let if_name = unsafe { *ifreq.ifr_ifrn.ifrn_name.as_ref() }.to_vec();
|
// We only access one field of the ifru union, hence this is safe.
|
||||||
|
let if_name = unsafe { ifreq.ifr_ifrn.ifrn_name }.to_vec();
|
||||||
|
|
||||||
// Try and update flags. Depending on how the tap was created (macvtap
|
// Try and update flags. Depending on how the tap was created (macvtap
|
||||||
// or via open_named()) this might return -EEXIST so we just ignore that.
|
// or via open_named()) this might return -EEXIST so we just ignore that.
|
||||||
unsafe {
|
unsafe {
|
||||||
let ifru_flags = ifreq.ifr_ifru.ifru_flags.as_mut();
|
ifreq.ifr_ifru.ifru_flags =
|
||||||
*ifru_flags =
|
|
||||||
(net_gen::IFF_TAP | net_gen::IFF_NO_PI | net_gen::IFF_VNET_HDR) as c_short;
|
(net_gen::IFF_TAP | net_gen::IFF_NO_PI | net_gen::IFF_VNET_HDR) as c_short;
|
||||||
if num_queue_pairs > 1 {
|
if num_queue_pairs > 1 {
|
||||||
*ifru_flags |= net_gen::IFF_MULTI_QUEUE as c_short;
|
ifreq.ifr_ifru.ifru_flags |= net_gen::IFF_MULTI_QUEUE as c_short;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let ret = unsafe { ioctl_with_mut_ref(&tap_file, net_gen::TUNSETIFF(), &mut ifreq) };
|
let ret = unsafe { ioctl_with_mut_ref(&tap_file, net_gen::TUNSETIFF(), &mut ifreq) };
|
||||||
@@ -204,11 +201,7 @@ impl Tap {
|
|||||||
|
|
||||||
let mut ifreq = self.get_ifreq();
|
let mut ifreq = self.get_ifreq();
|
||||||
|
|
||||||
// We only access one field of the ifru union, hence this is safe.
|
ifreq.ifr_ifru.ifru_addr = addr;
|
||||||
unsafe {
|
|
||||||
let ifru_addr = ifreq.ifr_ifru.ifru_addr.as_mut();
|
|
||||||
*ifru_addr = addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
||||||
#[allow(clippy::cast_lossless)]
|
#[allow(clippy::cast_lossless)]
|
||||||
@@ -245,9 +238,9 @@ impl Tap {
|
|||||||
}
|
}
|
||||||
// We only access one field of the ifru union, hence this is safe.
|
// We only access one field of the ifru union, hence this is safe.
|
||||||
unsafe {
|
unsafe {
|
||||||
let ifru_hwaddr = ifreq.ifr_ifru.ifru_hwaddr.as_mut();
|
let ifru_hwaddr = &mut ifreq.ifr_ifru.ifru_hwaddr;
|
||||||
for (i, v) in addr.get_bytes().iter().enumerate() {
|
for (i, v) in addr.get_bytes().iter().enumerate() {
|
||||||
ifru_hwaddr.sa_data[i] = *v as c_char;
|
ifru_hwaddr.sa_data[i] = *v as c_uchar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,11 +271,8 @@ impl Tap {
|
|||||||
|
|
||||||
// We only access one field of the ifru union, hence this is safe.
|
// We only access one field of the ifru union, hence this is safe.
|
||||||
let addr = unsafe {
|
let addr = unsafe {
|
||||||
let ifru_hwaddr = ifreq.ifr_ifru.ifru_hwaddr.as_ref();
|
MacAddr::from_bytes(&ifreq.ifr_ifru.ifru_hwaddr.sa_data[0..MAC_ADDR_LEN])
|
||||||
MacAddr::from_bytes(
|
.map_err(Error::MacParsing)?
|
||||||
&*(&ifru_hwaddr.sa_data[0..MAC_ADDR_LEN] as *const _ as *const [u8]),
|
|
||||||
)
|
|
||||||
.map_err(Error::MacParsing)?
|
|
||||||
};
|
};
|
||||||
Ok(addr)
|
Ok(addr)
|
||||||
}
|
}
|
||||||
@@ -294,11 +284,7 @@ impl Tap {
|
|||||||
|
|
||||||
let mut ifreq = self.get_ifreq();
|
let mut ifreq = self.get_ifreq();
|
||||||
|
|
||||||
// We only access one field of the ifru union, hence this is safe.
|
ifreq.ifr_ifru.ifru_addr = addr;
|
||||||
unsafe {
|
|
||||||
let ifru_addr = ifreq.ifr_ifru.ifru_addr.as_mut();
|
|
||||||
*ifru_addr = addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
||||||
#[allow(clippy::cast_lossless)]
|
#[allow(clippy::cast_lossless)]
|
||||||
@@ -338,7 +324,7 @@ impl Tap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If TAP device is already up don't try and enable it
|
// If TAP device is already up don't try and enable it
|
||||||
let ifru_flags = unsafe { ifreq.ifr_ifru.ifru_flags.as_ref() };
|
let ifru_flags = unsafe { ifreq.ifr_ifru.ifru_flags };
|
||||||
if ifru_flags
|
if ifru_flags
|
||||||
& (net_gen::net_device_flags_IFF_UP | net_gen::net_device_flags_IFF_RUNNING) as i16
|
& (net_gen::net_device_flags_IFF_UP | net_gen::net_device_flags_IFF_RUNNING) as i16
|
||||||
== (net_gen::net_device_flags_IFF_UP | net_gen::net_device_flags_IFF_RUNNING) as i16
|
== (net_gen::net_device_flags_IFF_UP | net_gen::net_device_flags_IFF_RUNNING) as i16
|
||||||
@@ -346,13 +332,8 @@ impl Tap {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// We only access one field of the ifru union, hence this is safe.
|
ifreq.ifr_ifru.ifru_flags =
|
||||||
unsafe {
|
(net_gen::net_device_flags_IFF_UP | net_gen::net_device_flags_IFF_RUNNING) as i16;
|
||||||
let ifru_flags = ifreq.ifr_ifru.ifru_flags.as_mut();
|
|
||||||
|
|
||||||
*ifru_flags =
|
|
||||||
(net_gen::net_device_flags_IFF_UP | net_gen::net_device_flags_IFF_RUNNING) as i16;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
||||||
#[allow(clippy::cast_lossless)]
|
#[allow(clippy::cast_lossless)]
|
||||||
@@ -631,18 +612,6 @@ mod tests {
|
|||||||
assert!(ret.is_ok());
|
assert!(ret.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_tap_get_ifreq() {
|
|
||||||
let _tap_ip_guard = TAP_IP_LOCK.lock().unwrap();
|
|
||||||
|
|
||||||
let tap = Tap::new(1).unwrap();
|
|
||||||
let ret = tap.get_ifreq();
|
|
||||||
assert_eq!(
|
|
||||||
"__BindgenUnionField",
|
|
||||||
format!("{:?}", ret.ifr_ifrn.ifrn_name)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_raw_fd() {
|
fn test_raw_fd() {
|
||||||
let _tap_ip_guard = TAP_IP_LOCK.lock().unwrap();
|
let _tap_ip_guard = TAP_IP_LOCK.lock().unwrap();
|
||||||
|
|||||||
@@ -10,11 +10,10 @@ byteorder = "1.4.3"
|
|||||||
hypervisor = { path = "../hypervisor" }
|
hypervisor = { path = "../hypervisor" }
|
||||||
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio-ioctls", branch = "master" }
|
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio-ioctls", branch = "master" }
|
||||||
vmm-sys-util = ">=0.3.1"
|
vmm-sys-util = ">=0.3.1"
|
||||||
libc = "0.2.94"
|
libc = "0.2.96"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
serde = {version = ">=1.0.27", features = ["rc"] }
|
versionize = "0.1.6"
|
||||||
serde_derive = ">=1.0.27"
|
versionize_derive = "0.1.4"
|
||||||
serde_json = ">=1.0.9"
|
|
||||||
vm-allocator = { path = "../vm-allocator" }
|
vm-allocator = { path = "../vm-allocator" }
|
||||||
vm-device = { path = "../vm-device" }
|
vm-device = { path = "../vm-device" }
|
||||||
vm-memory = "0.5.0"
|
vm-memory = "0.5.0"
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ use crate::{MsixConfig, PciInterruptPin};
|
|||||||
use byteorder::{ByteOrder, LittleEndian};
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable};
|
use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult};
|
||||||
|
use versionize_derive::Versionize;
|
||||||
|
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
|
||||||
|
|
||||||
// The number of 32bit registers in the config space, 4096 bytes.
|
// The number of 32bit registers in the config space, 4096 bytes.
|
||||||
const NUM_CONFIGURATION_REGISTERS: usize = 1024;
|
const NUM_CONFIGURATION_REGISTERS: usize = 1024;
|
||||||
@@ -276,7 +278,7 @@ fn decode_64_bits_bar_size(bar_size_hi: u32, bar_size_lo: u32) -> Option<u64> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Default, Clone, Copy)]
|
#[derive(Default, Clone, Copy, Versionize)]
|
||||||
struct PciBar {
|
struct PciBar {
|
||||||
addr: u32,
|
addr: u32,
|
||||||
size: u32,
|
size: u32,
|
||||||
@@ -284,7 +286,7 @@ struct PciBar {
|
|||||||
r#type: Option<PciBarRegionType>,
|
r#type: Option<PciBarRegionType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Versionize)]
|
||||||
struct PciConfigurationState {
|
struct PciConfigurationState {
|
||||||
registers: Vec<u32>,
|
registers: Vec<u32>,
|
||||||
writable_bits: Vec<u32>,
|
writable_bits: Vec<u32>,
|
||||||
@@ -296,6 +298,8 @@ struct PciConfigurationState {
|
|||||||
msix_cap_reg_idx: Option<usize>,
|
msix_cap_reg_idx: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl VersionMapped for PciConfigurationState {}
|
||||||
|
|
||||||
/// Contains the configuration space of a PCI node.
|
/// Contains the configuration space of a PCI node.
|
||||||
/// See the [specification](https://en.wikipedia.org/wiki/PCI_configuration_space).
|
/// See the [specification](https://en.wikipedia.org/wiki/PCI_configuration_space).
|
||||||
/// The configuration space is accessed with DWORD reads and writes from the guest.
|
/// The configuration space is accessed with DWORD reads and writes from the guest.
|
||||||
@@ -313,7 +317,7 @@ pub struct PciConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// See pci_regs.h in kernel
|
/// See pci_regs.h in kernel
|
||||||
#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, PartialEq, Versionize)]
|
||||||
pub enum PciBarRegionType {
|
pub enum PciBarRegionType {
|
||||||
Memory32BitRegion = 0,
|
Memory32BitRegion = 0,
|
||||||
IoRegion = 0x01,
|
IoRegion = 0x01,
|
||||||
@@ -881,11 +885,11 @@ impl Snapshottable for PciConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||||
Snapshot::new_from_state(&self.id(), &self.state())
|
Snapshot::new_from_versioned_state(&self.id(), &self.state())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
|
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
|
||||||
self.set_state(&snapshot.to_state(&self.id())?);
|
self.set_state(&snapshot.to_versioned_state(&self.id())?);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,6 @@
|
|||||||
//! Implements pci devices and busses.
|
//! Implements pci devices and busses.
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
extern crate hypervisor;
|
|
||||||
extern crate serde;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate serde_derive;
|
|
||||||
extern crate serde_json;
|
|
||||||
extern crate vm_memory;
|
|
||||||
|
|
||||||
mod bus;
|
mod bus;
|
||||||
mod configuration;
|
mod configuration;
|
||||||
|
|||||||
@@ -3,9 +3,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
|
||||||
//
|
//
|
||||||
|
|
||||||
extern crate byteorder;
|
|
||||||
extern crate vm_memory;
|
|
||||||
|
|
||||||
use byteorder::{ByteOrder, LittleEndian};
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vm_device::interrupt::{
|
use vm_device::interrupt::{
|
||||||
|
|||||||
@@ -3,20 +3,19 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
|
||||||
//
|
//
|
||||||
|
|
||||||
extern crate byteorder;
|
|
||||||
extern crate vm_memory;
|
|
||||||
|
|
||||||
use crate::{PciCapability, PciCapabilityId};
|
use crate::{PciCapability, PciCapabilityId};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use byteorder::{ByteOrder, LittleEndian};
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||||
|
use versionize_derive::Versionize;
|
||||||
use vm_device::interrupt::{
|
use vm_device::interrupt::{
|
||||||
InterruptIndex, InterruptSourceConfig, InterruptSourceGroup, MsiIrqSourceConfig,
|
InterruptIndex, InterruptSourceConfig, InterruptSourceGroup, MsiIrqSourceConfig,
|
||||||
};
|
};
|
||||||
use vm_memory::ByteValued;
|
use vm_memory::ByteValued;
|
||||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable};
|
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
|
||||||
|
|
||||||
const MAX_MSIX_VECTORS_PER_DEVICE: u16 = 2048;
|
const MAX_MSIX_VECTORS_PER_DEVICE: u16 = 2048;
|
||||||
const MSIX_TABLE_ENTRIES_MODULO: u64 = 16;
|
const MSIX_TABLE_ENTRIES_MODULO: u64 = 16;
|
||||||
@@ -36,7 +35,7 @@ enum Error {
|
|||||||
UpdateInterruptRoute(io::Error),
|
UpdateInterruptRoute(io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Versionize)]
|
||||||
pub struct MsixTableEntry {
|
pub struct MsixTableEntry {
|
||||||
pub msg_addr_lo: u32,
|
pub msg_addr_lo: u32,
|
||||||
pub msg_addr_hi: u32,
|
pub msg_addr_hi: u32,
|
||||||
@@ -61,7 +60,7 @@ impl Default for MsixTableEntry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Versionize)]
|
||||||
struct MsixConfigState {
|
struct MsixConfigState {
|
||||||
table_entries: Vec<MsixTableEntry>,
|
table_entries: Vec<MsixTableEntry>,
|
||||||
pba_entries: Vec<u64>,
|
pba_entries: Vec<u64>,
|
||||||
@@ -69,6 +68,8 @@ struct MsixConfigState {
|
|||||||
enabled: bool,
|
enabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl VersionMapped for MsixConfigState {}
|
||||||
|
|
||||||
pub struct MsixConfig {
|
pub struct MsixConfig {
|
||||||
pub table_entries: Vec<MsixTableEntry>,
|
pub table_entries: Vec<MsixTableEntry>,
|
||||||
pub pba_entries: Vec<u64>,
|
pub pba_entries: Vec<u64>,
|
||||||
@@ -432,11 +433,11 @@ impl Snapshottable for MsixConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||||
Snapshot::new_from_state(&self.id(), &self.state())
|
Snapshot::new_from_versioned_state(&self.id(), &self.state())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
|
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
|
||||||
self.set_state(&snapshot.to_state(&self.id())?)
|
self.set_state(&snapshot.to_versioned_state(&self.id())?)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
MigratableError::Restore(anyhow!(
|
MigratableError::Restore(anyhow!(
|
||||||
"Could not restore state for {}: {:?}",
|
"Could not restore state for {}: {:?}",
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
|
||||||
//
|
//
|
||||||
|
|
||||||
extern crate vm_allocator;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
msi_num_enabled_vectors, BarReprogrammingParams, MsiConfig, MsixCap, MsixConfig,
|
msi_num_enabled_vectors, BarReprogrammingParams, MsiConfig, MsixCap, MsixConfig,
|
||||||
PciBarConfiguration, PciBarRegionType, PciCapabilityId, PciClassCode, PciConfiguration,
|
PciBarConfiguration, PciBarRegionType, PciCapabilityId, PciClassCode, PciConfiguration,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ path = "src/qcow.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
libc = "0.2.94"
|
libc = "0.2.96"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
remain = "0.2.2"
|
remain = "0.2.2"
|
||||||
vmm-sys-util = ">=0.3.1"
|
vmm-sys-util = ">=0.3.1"
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ version = "0.1.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2.94"
|
libc = "0.2.96"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
vmm-sys-util = "0.8.0"
|
vmm-sys-util = "0.8.0"
|
||||||
|
|||||||
@@ -1,3 +1,10 @@
|
|||||||
|
- [v16.0](#v160)
|
||||||
|
- [Improved live migration support](#improved-live-migration-support)
|
||||||
|
- [Improved `vhost-user` support](#improved-vhost-user-support)
|
||||||
|
- [ARM64 ACPI and UEFI support](#arm64-acpi-and-uefi-support)
|
||||||
|
- [Notable bug fixes](#notable-bug-fixes)
|
||||||
|
- [Removed functionality](#removed-functionality)
|
||||||
|
- [Contributors](#contributors)
|
||||||
- [v15.0](#v150)
|
- [v15.0](#v150)
|
||||||
- [Version numbering and stability guarantees](#version-numbering-and-stability-guarantees)
|
- [Version numbering and stability guarantees](#version-numbering-and-stability-guarantees)
|
||||||
- [Network device rate limiting](#network-device-rate-limiting)
|
- [Network device rate limiting](#network-device-rate-limiting)
|
||||||
@@ -5,7 +12,7 @@
|
|||||||
- [`--api-socket` supports file descriptor parameter](#--api-socket-supports-file-descriptor-parameter)
|
- [`--api-socket` supports file descriptor parameter](#--api-socket-supports-file-descriptor-parameter)
|
||||||
- [Bug fixes](#bug-fixes)
|
- [Bug fixes](#bug-fixes)
|
||||||
- [Deprecations](#deprecations)
|
- [Deprecations](#deprecations)
|
||||||
- [Contributors](#contributors)
|
- [Contributors](#contributors-1)
|
||||||
- [v0.14.1](#v0141)
|
- [v0.14.1](#v0141)
|
||||||
- [v0.14.0](#v0140)
|
- [v0.14.0](#v0140)
|
||||||
- [Structured event monitoring](#structured-event-monitoring)
|
- [Structured event monitoring](#structured-event-monitoring)
|
||||||
@@ -15,7 +22,7 @@
|
|||||||
- [PTY control for serial and `virtio-console`](#pty-control-for-serial-and-virtio-console)
|
- [PTY control for serial and `virtio-console`](#pty-control-for-serial-and-virtio-console)
|
||||||
- [Block device rate limiting](#block-device-rate-limiting)
|
- [Block device rate limiting](#block-device-rate-limiting)
|
||||||
- [Deprecations](#deprecations-1)
|
- [Deprecations](#deprecations-1)
|
||||||
- [Contributors](#contributors-1)
|
- [Contributors](#contributors-2)
|
||||||
- [v0.13.0](#v0130)
|
- [v0.13.0](#v0130)
|
||||||
- [Wider VFIO device support](#wider-vfio-device-support)
|
- [Wider VFIO device support](#wider-vfio-device-support)
|
||||||
- [Improved huge page support](#improved-huge-page-support)
|
- [Improved huge page support](#improved-huge-page-support)
|
||||||
@@ -23,13 +30,13 @@
|
|||||||
- [VHD disk image support](#vhd-disk-image-support)
|
- [VHD disk image support](#vhd-disk-image-support)
|
||||||
- [Improved Virtio device threading](#improved-virtio-device-threading)
|
- [Improved Virtio device threading](#improved-virtio-device-threading)
|
||||||
- [Clean shutdown support via synthetic power button](#clean-shutdown-support-via-synthetic-power-button)
|
- [Clean shutdown support via synthetic power button](#clean-shutdown-support-via-synthetic-power-button)
|
||||||
- [Contributors](#contributors-2)
|
- [Contributors](#contributors-3)
|
||||||
- [v0.12.0](#v0120)
|
- [v0.12.0](#v0120)
|
||||||
- [ARM64 enhancements](#arm64-enhancements)
|
- [ARM64 enhancements](#arm64-enhancements)
|
||||||
- [Removal of `vhost-user-net` and `vhost-user-block` self spawning](#removal-of-vhost-user-net-and-vhost-user-block-self-spawning)
|
- [Removal of `vhost-user-net` and `vhost-user-block` self spawning](#removal-of-vhost-user-net-and-vhost-user-block-self-spawning)
|
||||||
- [Migration of `vhost-user-fs` backend](#migration-of-vhost-user-fs-backend)
|
- [Migration of `vhost-user-fs` backend](#migration-of-vhost-user-fs-backend)
|
||||||
- [Enhanced "info" API](#enhanced-info-api)
|
- [Enhanced "info" API](#enhanced-info-api)
|
||||||
- [Contributors](#contributors-3)
|
- [Contributors](#contributors-4)
|
||||||
- [v0.11.0](#v0110)
|
- [v0.11.0](#v0110)
|
||||||
- [`io_uring` support by default for `virtio-block`](#io_uring-support-by-default-for-virtio-block)
|
- [`io_uring` support by default for `virtio-block`](#io_uring-support-by-default-for-virtio-block)
|
||||||
- [Windows Guest Support](#windows-guest-support)
|
- [Windows Guest Support](#windows-guest-support)
|
||||||
@@ -41,15 +48,15 @@
|
|||||||
- [Default Log Level Changed](#default-log-level-changed)
|
- [Default Log Level Changed](#default-log-level-changed)
|
||||||
- [New `--balloon` Parameter Added](#new---balloon-parameter-added)
|
- [New `--balloon` Parameter Added](#new---balloon-parameter-added)
|
||||||
- [Experimental `virtio-watchdog` Support](#experimental-virtio-watchdog-support)
|
- [Experimental `virtio-watchdog` Support](#experimental-virtio-watchdog-support)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes)
|
- [Notable Bug Fixes](#notable-bug-fixes-1)
|
||||||
- [Contributors](#contributors-4)
|
- [Contributors](#contributors-5)
|
||||||
- [v0.10.0](#v0100)
|
- [v0.10.0](#v0100)
|
||||||
- [`virtio-block` Support for Multiple Descriptors](#virtio-block-support-for-multiple-descriptors)
|
- [`virtio-block` Support for Multiple Descriptors](#virtio-block-support-for-multiple-descriptors)
|
||||||
- [Memory Zones](#memory-zones)
|
- [Memory Zones](#memory-zones)
|
||||||
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements)
|
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements)
|
||||||
- [Preliminary KVM HyperV Emulation Control](#preliminary-kvm-hyperv-emulation-control)
|
- [Preliminary KVM HyperV Emulation Control](#preliminary-kvm-hyperv-emulation-control)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-1)
|
- [Notable Bug Fixes](#notable-bug-fixes-2)
|
||||||
- [Contributors](#contributors-5)
|
- [Contributors](#contributors-6)
|
||||||
- [v0.9.0](#v090)
|
- [v0.9.0](#v090)
|
||||||
- [`io_uring` Based Block Device Support](#io_uring-based-block-device-support)
|
- [`io_uring` Based Block Device Support](#io_uring-based-block-device-support)
|
||||||
- [Block and Network Device Statistics](#block-and-network-device-statistics)
|
- [Block and Network Device Statistics](#block-and-network-device-statistics)
|
||||||
@@ -62,17 +69,17 @@
|
|||||||
- [Enhancements to ARM64 Support](#enhancements-to-arm64-support)
|
- [Enhancements to ARM64 Support](#enhancements-to-arm64-support)
|
||||||
- [Intel SGX Support](#intel-sgx-support)
|
- [Intel SGX Support](#intel-sgx-support)
|
||||||
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements-1)
|
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements-1)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-2)
|
- [Notable Bug Fixes](#notable-bug-fixes-3)
|
||||||
- [Contributors](#contributors-6)
|
- [Contributors](#contributors-7)
|
||||||
- [v0.8.0](#v080)
|
- [v0.8.0](#v080)
|
||||||
- [Experimental Snapshot and Restore Support](#experimental-snapshot-and-restore-support)
|
- [Experimental Snapshot and Restore Support](#experimental-snapshot-and-restore-support)
|
||||||
- [Experimental ARM64 Support](#experimental-arm64-support)
|
- [Experimental ARM64 Support](#experimental-arm64-support)
|
||||||
- [Support for Using 5-level Paging in Guests](#support-for-using-5-level-paging-in-guests)
|
- [Support for Using 5-level Paging in Guests](#support-for-using-5-level-paging-in-guests)
|
||||||
- [Virtio Device Interrupt Suppression for Network Devices](#virtio-device-interrupt-suppression-for-network-devices)
|
- [Virtio Device Interrupt Suppression for Network Devices](#virtio-device-interrupt-suppression-for-network-devices)
|
||||||
- [`vhost_user_fs` Improvements](#vhost_user_fs-improvements)
|
- [`vhost_user_fs` Improvements](#vhost_user_fs-improvements)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-3)
|
- [Notable Bug Fixes](#notable-bug-fixes-4)
|
||||||
- [Command Line and API Changes](#command-line-and-api-changes)
|
- [Command Line and API Changes](#command-line-and-api-changes)
|
||||||
- [Contributors](#contributors-7)
|
- [Contributors](#contributors-8)
|
||||||
- [v0.7.0](#v070)
|
- [v0.7.0](#v070)
|
||||||
- [Block, Network, Persistent Memory (PMEM), VirtioFS and Vsock hotplug](#block-network-persistent-memory-pmem-virtiofs-and-vsock-hotplug)
|
- [Block, Network, Persistent Memory (PMEM), VirtioFS and Vsock hotplug](#block-network-persistent-memory-pmem-virtiofs-and-vsock-hotplug)
|
||||||
- [Alternative `libc` Support](#alternative-libc-support)
|
- [Alternative `libc` Support](#alternative-libc-support)
|
||||||
@@ -82,14 +89,14 @@
|
|||||||
- [`Seccomp` Sandboxing](#seccomp-sandboxing)
|
- [`Seccomp` Sandboxing](#seccomp-sandboxing)
|
||||||
- [Updated Distribution Support](#updated-distribution-support)
|
- [Updated Distribution Support](#updated-distribution-support)
|
||||||
- [Command Line and API Changes](#command-line-and-api-changes-1)
|
- [Command Line and API Changes](#command-line-and-api-changes-1)
|
||||||
- [Contributors](#contributors-8)
|
- [Contributors](#contributors-9)
|
||||||
- [v0.6.0](#v060)
|
- [v0.6.0](#v060)
|
||||||
- [Directly Assigned Devices Hotplug](#directly-assigned-devices-hotplug)
|
- [Directly Assigned Devices Hotplug](#directly-assigned-devices-hotplug)
|
||||||
- [Shared Filesystem Improvements](#shared-filesystem-improvements)
|
- [Shared Filesystem Improvements](#shared-filesystem-improvements)
|
||||||
- [Block and Networking IO Self Offloading](#block-and-networking-io-self-offloading)
|
- [Block and Networking IO Self Offloading](#block-and-networking-io-self-offloading)
|
||||||
- [Command Line Interface](#command-line-interface)
|
- [Command Line Interface](#command-line-interface)
|
||||||
- [PVH Boot](#pvh-boot)
|
- [PVH Boot](#pvh-boot)
|
||||||
- [Contributors](#contributors-9)
|
- [Contributors](#contributors-10)
|
||||||
- [v0.5.1](#v051)
|
- [v0.5.1](#v051)
|
||||||
- [v0.5.0](#v050)
|
- [v0.5.0](#v050)
|
||||||
- [Virtual Machine Dynamic Resizing](#virtual-machine-dynamic-resizing)
|
- [Virtual Machine Dynamic Resizing](#virtual-machine-dynamic-resizing)
|
||||||
@@ -97,7 +104,7 @@
|
|||||||
- [New Interrupt Management Framework](#new-interrupt-management-framework)
|
- [New Interrupt Management Framework](#new-interrupt-management-framework)
|
||||||
- [Development Tools](#development-tools)
|
- [Development Tools](#development-tools)
|
||||||
- [Kata Containers Integration](#kata-containers-integration)
|
- [Kata Containers Integration](#kata-containers-integration)
|
||||||
- [Contributors](#contributors-10)
|
- [Contributors](#contributors-11)
|
||||||
- [v0.4.0](#v040)
|
- [v0.4.0](#v040)
|
||||||
- [Dynamic virtual CPUs addition](#dynamic-virtual-cpus-addition)
|
- [Dynamic virtual CPUs addition](#dynamic-virtual-cpus-addition)
|
||||||
- [Programmatic firmware tables generation](#programmatic-firmware-tables-generation)
|
- [Programmatic firmware tables generation](#programmatic-firmware-tables-generation)
|
||||||
@@ -106,7 +113,7 @@
|
|||||||
- [Userspace IOAPIC by default](#userspace-ioapic-by-default)
|
- [Userspace IOAPIC by default](#userspace-ioapic-by-default)
|
||||||
- [PCI BAR reprogramming](#pci-bar-reprogramming)
|
- [PCI BAR reprogramming](#pci-bar-reprogramming)
|
||||||
- [New `cloud-hypervisor` organization](#new-cloud-hypervisor-organization)
|
- [New `cloud-hypervisor` organization](#new-cloud-hypervisor-organization)
|
||||||
- [Contributors](#contributors-11)
|
- [Contributors](#contributors-12)
|
||||||
- [v0.3.0](#v030)
|
- [v0.3.0](#v030)
|
||||||
- [Block device offloading](#block-device-offloading)
|
- [Block device offloading](#block-device-offloading)
|
||||||
- [Network device backend](#network-device-backend)
|
- [Network device backend](#network-device-backend)
|
||||||
@@ -133,6 +140,55 @@
|
|||||||
- [Unit testing](#unit-testing)
|
- [Unit testing](#unit-testing)
|
||||||
- [Integration tests parallelization](#integration-tests-parallelization)
|
- [Integration tests parallelization](#integration-tests-parallelization)
|
||||||
|
|
||||||
|
# v16.0
|
||||||
|
|
||||||
|
This release has been tracked through the [v16.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/19).
|
||||||
|
|
||||||
|
### Improved live migration support
|
||||||
|
|
||||||
|
The live migration support inside Cloud Hypervisor has been improved with the addition of the tracking of dirty pages written by the VMM to complement the tracking of dirty pages made by the guest itself. Further the internal state of the VMM now is versioned which allows the safe migration of VMs from one version of the VMM to a newer one. However further testing is required so this should be done with care. See the [live migration documentation](docs/live_migration.md) for more details.
|
||||||
|
|
||||||
|
### Improved `vhost-user` support
|
||||||
|
|
||||||
|
When using `vhost-user` to access devices implemented in different processes there is now support for reconnection of those devices in the case of a restart of the backend. In addition it is now possible to operate with the direction of the `vhost-user-net` connection reversed with the server in the VMM and the client in the backend. This is aligns with the default approach recommended by Open vSwitch.
|
||||||
|
|
||||||
|
### ARM64 ACPI and UEFI support
|
||||||
|
|
||||||
|
Cloud Hypervisor now supports using ACPI and booting from a UEFI image on ARM64. This allows the use of stock OS images without direct kernel boot.
|
||||||
|
|
||||||
|
### Notable bug fixes
|
||||||
|
|
||||||
|
* Activating fewer `virtio-net` queues than advertised is now supported. This appeared when using OVMF with an MQ enabled device (#2578).
|
||||||
|
* When using MQ with `virtio` devices Cloud Hypervisor now enforces a minimum vCPU count which ensures that the user will not see adverse guest performance (#2563).
|
||||||
|
* The KVM clock is now correctly handled during live migration / snapshot & restore.
|
||||||
|
|
||||||
|
### Removed functionality
|
||||||
|
|
||||||
|
The following formerly deprecated features have been removed:
|
||||||
|
|
||||||
|
* Support for booting with the "LinuxBoot" protocol for ELF and `bzImage`
|
||||||
|
binaries has been deprecated. When using direct boot users should configure
|
||||||
|
their kernel with `CONFIG_PVH=y`.
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
|
||||||
|
Many thanks to everyone who has contributed to our release including some new faces.
|
||||||
|
|
||||||
|
* Anatol Belski <anbelski@linux.microsoft.com>
|
||||||
|
* Bo Chen <chen.bo@intel.com>
|
||||||
|
* Dayu Liu <liu.dayu@zte.com.cn>
|
||||||
|
* Henry Wang <Henry.Wang@arm.com>
|
||||||
|
* Jiachen Zhang <zhangjiachen.jaycee@bytedance.com>
|
||||||
|
* Jianyong Wu <jianyong.wu@arm.com>
|
||||||
|
* Michael Zhao <michael.zhao@arm.com>
|
||||||
|
* Mikko Ylinen <mikko.ylinen@intel.com>
|
||||||
|
* Muminul Islam <muislam@microsoft.com>
|
||||||
|
* Ren Lei <ren.lei4@zte.com.cn>
|
||||||
|
* Rob Bradford <robert.bradford@intel.com>
|
||||||
|
* Sebastien Boeuf <sebastien.boeuf@intel.com>
|
||||||
|
* Wei Liu <liuwe@microsoft.com>
|
||||||
|
* Yi Wang <wang.yi59@zte.com.cn>
|
||||||
|
|
||||||
# v15.0
|
# v15.0
|
||||||
|
|
||||||
This release has been tracked through the [v15.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/18).
|
This release has been tracked through the [v15.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/18).
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
FROM ubuntu:20.04 as dev
|
FROM ubuntu:20.04 as dev
|
||||||
|
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
ARG RUST_TOOLCHAIN="1.51.0"
|
ARG RUST_TOOLCHAIN="1.52.1"
|
||||||
ARG CLH_SRC_DIR="/cloud-hypervisor"
|
ARG CLH_SRC_DIR="/cloud-hypervisor"
|
||||||
ARG CLH_BUILD_DIR="$CLH_SRC_DIR/build"
|
ARG CLH_BUILD_DIR="$CLH_SRC_DIR/build"
|
||||||
ARG CARGO_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_registry"
|
ARG CARGO_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_registry"
|
||||||
@@ -37,11 +37,18 @@ RUN apt-get update \
|
|||||||
socat \
|
socat \
|
||||||
dosfstools \
|
dosfstools \
|
||||||
cpio \
|
cpio \
|
||||||
libfdt-dev \
|
python \
|
||||||
|
python3 \
|
||||||
python3-setuptools \
|
python3-setuptools \
|
||||||
|
ntfs-3g \
|
||||||
|
openvswitch-switch-dpdk \
|
||||||
|
python3-distutils \
|
||||||
|
uuid-dev \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN update-alternatives --set ovs-vswitchd /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk
|
||||||
|
|
||||||
RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
||||||
apt-get update \
|
apt-get update \
|
||||||
&& apt-get -yq upgrade \
|
&& apt-get -yq upgrade \
|
||||||
@@ -56,14 +63,7 @@ RUN if [ "$TARGETARCH" = "arm64" ]; then \
|
|||||||
&& apt-get -yq upgrade \
|
&& apt-get -yq upgrade \
|
||||||
&& DEBIAN_FRONTEND=noninteractive apt-get install -yq libcap2-bin \
|
&& DEBIAN_FRONTEND=noninteractive apt-get install -yq libcap2-bin \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
&& rm -rf /var/lib/apt/lists/*; fi
|
||||||
# Build and install the musl-gcc version of libfdt. This is to ensure
|
|
||||||
# the cloud-hypervisor binary can be built and linked using musl toolchain.
|
|
||||||
&& git clone https://github.com/dgibson/dtc.git && cd dtc \
|
|
||||||
&& sed -i 's/$(LIBFDT_archive) $(LIBFDT_lib)/$(LIBFDT_archive)/g' Makefile \
|
|
||||||
&& export CC=musl-gcc && make libfdt \
|
|
||||||
&& cp libfdt/libfdt.a /usr/lib/aarch64-linux-musl \
|
|
||||||
&& rm -rf /dtc; fi
|
|
||||||
|
|
||||||
# Fix the libssl-dev install
|
# Fix the libssl-dev install
|
||||||
RUN export ARCH="$(uname -m)" \
|
RUN export ARCH="$(uname -m)" \
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
Name: cloud-hypervisor
|
Name: cloud-hypervisor
|
||||||
Summary: Cloud Hypervisor is an open source Virtual Machine Monitor (VMM) that runs on top of KVM.
|
Summary: Cloud Hypervisor is an open source Virtual Machine Monitor (VMM) that runs on top of KVM.
|
||||||
Version: 0.13.0
|
Version: 15.0
|
||||||
Release: 0%{?dist}
|
Release: 0%{?dist}
|
||||||
License: ASL 2.0 or BSD-3-clause
|
License: ASL 2.0 or BSD-3-clause
|
||||||
Group: Applications/System
|
Group: Applications/System
|
||||||
@@ -88,5 +88,8 @@ setcap cap_net_admin+ep %{_libdir}/cloud-hypervisor/static/vhost_user_net
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Fri May 28 2021 Muminul Islam <muislam@microsoft.com> 15.0-0
|
||||||
|
- Update version to 15.0
|
||||||
|
|
||||||
* Wed Jul 22 2020 Muminul Islam <muislam@microsoft.com> 0.8.0-0
|
* Wed Jul 22 2020 Muminul Islam <muislam@microsoft.com> 0.8.0-0
|
||||||
- Initial version
|
- Initial version
|
||||||
|
|||||||
@@ -8,9 +8,73 @@ export BUILD_TARGET=${BUILD_TARGET-aarch64-unknown-linux-gnu}
|
|||||||
|
|
||||||
WORKLOADS_DIR="$HOME/workloads"
|
WORKLOADS_DIR="$HOME/workloads"
|
||||||
WORKLOADS_LOCK="$WORKLOADS_DIR/integration_test.lock"
|
WORKLOADS_LOCK="$WORKLOADS_DIR/integration_test.lock"
|
||||||
|
EDK2_BUILD_DIR="$WORKLOADS_DIR/edk2_build"
|
||||||
|
|
||||||
mkdir -p "$WORKLOADS_DIR"
|
mkdir -p "$WORKLOADS_DIR"
|
||||||
|
|
||||||
|
build_edk2() {
|
||||||
|
EDK2_REPO="https://github.com/cloud-hypervisor/edk2.git"
|
||||||
|
EDK2_DIR="edk2"
|
||||||
|
EDK2_BRANCH="ch-aarch64"
|
||||||
|
EDK2_PLAT_REPO="https://github.com/tianocore/edk2-platforms.git"
|
||||||
|
EDK2_PLAT_DIR="edk2-platforms"
|
||||||
|
ACPICA_REPO="https://github.com/acpica/acpica.git"
|
||||||
|
ACPICA_DIR="acpica"
|
||||||
|
|
||||||
|
export WORKSPACE="$EDK2_BUILD_DIR"
|
||||||
|
export PACKAGES_PATH="$WORKSPACE/$EDK2_DIR:$WORKSPACE/$EDK2_PLAT_DIR"
|
||||||
|
export IASL_PREFIX="$WORKSPACE/acpica/generate/unix/bin/"
|
||||||
|
|
||||||
|
cd "$WORKLOADS_DIR"
|
||||||
|
if [ ! -d "$WORKSPACE" ]; then
|
||||||
|
mkdir -p "$WORKSPACE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
pushd "$WORKSPACE"
|
||||||
|
|
||||||
|
# Check whether the local HEAD commit same as the remote HEAD or not. Remove the folder if they are different.
|
||||||
|
if [ -d "$EDK2_DIR" ]; then
|
||||||
|
pushd $EDK2_DIR
|
||||||
|
git fetch
|
||||||
|
EDK2_LOCAL_HEAD=$(git rev-parse HEAD)
|
||||||
|
EDK2_REMOTE_HEAD=$(git rev-parse remotes/origin/$EDK2_BRANCH)
|
||||||
|
popd
|
||||||
|
if [ "$EDK2_LOCAL_HEAD" != "$EDK2_REMOTE_HEAD" ]; then
|
||||||
|
# If EDK2 code is out of date, remove and rebuild all
|
||||||
|
rm -rf "$EDK2_DIR"
|
||||||
|
rm -rf "$EDK2_PLAT_DIR"
|
||||||
|
rm -rf "$ACPICA_DIR"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$EDK2_DIR" ]; then
|
||||||
|
time git clone --depth 1 "$EDK2_REPO" -b "$EDK2_BRANCH" "$EDK2_DIR"
|
||||||
|
pushd $EDK2_DIR
|
||||||
|
git submodule update --init
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$EDK2_PLAT_DIR" ]; then
|
||||||
|
time git clone --depth 1 "$EDK2_PLAT_REPO" -b master "$EDK2_PLAT_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$ACPICA_DIR" ]; then
|
||||||
|
time git clone --depth 1 "$ACPICA_REPO" -b master "$ACPICA_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
make -C "$ACPICA_DIR"/
|
||||||
|
|
||||||
|
source edk2/edksetup.sh
|
||||||
|
make -C edk2/BaseTools
|
||||||
|
|
||||||
|
build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtCloudHv.dsc -b RELEASE
|
||||||
|
cp Build/ArmVirtCloudHv-AARCH64/RELEASE_GCC5/FV/CLOUDHV_EFI.fd "$WORKLOADS_DIR"
|
||||||
|
|
||||||
|
echo "Info: build UEFI successfully"
|
||||||
|
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
update_workloads() {
|
update_workloads() {
|
||||||
cp scripts/sha1sums-aarch64 $WORKLOADS_DIR
|
cp scripts/sha1sums-aarch64 $WORKLOADS_DIR
|
||||||
|
|
||||||
@@ -176,6 +240,9 @@ update_workloads() {
|
|||||||
echo "foo" > "$SHARED_DIR/file1"
|
echo "foo" > "$SHARED_DIR/file1"
|
||||||
echo "bar" > "$SHARED_DIR/file3" || exit 1
|
echo "bar" > "$SHARED_DIR/file3" || exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check and build EDK2 binary
|
||||||
|
build_edk2
|
||||||
}
|
}
|
||||||
|
|
||||||
process_common_args "$@"
|
process_common_args "$@"
|
||||||
@@ -186,8 +253,10 @@ if [[ "$hypervisor" = "mshv" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
features_build="--no-default-features --features $hypervisor "
|
features_build_fdt="--no-default-features --features $hypervisor"
|
||||||
features_test="--no-default-features --features integration_tests,$hypervisor"
|
features_build_acpi="--no-default-features --features $hypervisor,acpi"
|
||||||
|
features_test_fdt="--no-default-features --features integration_tests,$hypervisor"
|
||||||
|
features_test_acpi="--no-default-features --features integration_tests,$hypervisor,acpi"
|
||||||
|
|
||||||
# lock the workloads folder to avoid parallel updating by different containers
|
# lock the workloads folder to avoid parallel updating by different containers
|
||||||
(
|
(
|
||||||
@@ -211,7 +280,10 @@ TARGET_CC="musl-gcc"
|
|||||||
CFLAGS="-I /usr/include/aarch64-linux-musl/ -idirafter /usr/include/"
|
CFLAGS="-I /usr/include/aarch64-linux-musl/ -idirafter /usr/include/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cargo build --all --release $features_build --target $BUILD_TARGET
|
export RUST_BACKTRACE=1
|
||||||
|
|
||||||
|
# Test without ACPI
|
||||||
|
cargo build --all --release $features_build_fdt --target $BUILD_TARGET
|
||||||
strip target/$BUILD_TARGET/release/cloud-hypervisor
|
strip target/$BUILD_TARGET/release/cloud-hypervisor
|
||||||
strip target/$BUILD_TARGET/release/vhost_user_net
|
strip target/$BUILD_TARGET/release/vhost_user_net
|
||||||
strip target/$BUILD_TARGET/release/ch-remote
|
strip target/$BUILD_TARGET/release/ch-remote
|
||||||
@@ -222,8 +294,27 @@ sudo bash -c "echo 1000000 > /sys/kernel/mm/ksm/pages_to_scan"
|
|||||||
sudo bash -c "echo 10 > /sys/kernel/mm/ksm/sleep_millisecs"
|
sudo bash -c "echo 10 > /sys/kernel/mm/ksm/sleep_millisecs"
|
||||||
sudo bash -c "echo 1 > /sys/kernel/mm/ksm/run"
|
sudo bash -c "echo 1 > /sys/kernel/mm/ksm/run"
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
# Setup ovs-dpdk
|
||||||
time cargo test $features_test "tests::parallel::$test_filter"
|
echo 2048 | sudo tee /proc/sys/vm/nr_hugepages
|
||||||
|
service openvswitch-switch start
|
||||||
|
ovs-vsctl init
|
||||||
|
ovs-vsctl set Open_vSwitch . other_config:dpdk-init=true
|
||||||
|
service openvswitch-switch restart
|
||||||
|
|
||||||
|
time cargo test $features_test_fdt "tests::parallel::$test_filter"
|
||||||
RES=$?
|
RES=$?
|
||||||
|
echo "Integration test on FDT finished with result $RES."
|
||||||
|
|
||||||
|
if [ $RES -eq 0 ]; then
|
||||||
|
# Test with EDK2 + ACPI
|
||||||
|
cargo build --all --release $features_build_acpi --target $BUILD_TARGET
|
||||||
|
strip target/$BUILD_TARGET/release/cloud-hypervisor
|
||||||
|
strip target/$BUILD_TARGET/release/vhost_user_net
|
||||||
|
strip target/$BUILD_TARGET/release/ch-remote
|
||||||
|
|
||||||
|
time cargo test $features_test_acpi "tests::parallel::test_edk2_acpi_launch"
|
||||||
|
RES=$?
|
||||||
|
echo "Integration test on UEFI & ACPI finished with result $RES."
|
||||||
|
fi
|
||||||
|
|
||||||
exit $RES
|
exit $RES
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ strip target/$BUILD_TARGET/release/cloud-hypervisor
|
|||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
|
|
||||||
time cargo test $features_test "tests::vfio::$test_filter"
|
time cargo test $features_test "tests::vfio::$test_filter" -- --test-threads=1
|
||||||
RES=$?
|
RES=$?
|
||||||
|
|
||||||
exit $RES
|
exit $RES
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export RUST_BACKTRACE=1
|
|||||||
|
|
||||||
# Only run with 1 thread to avoid tests interfering with one another because
|
# Only run with 1 thread to avoid tests interfering with one another because
|
||||||
# Windows has a static IP configured
|
# Windows has a static IP configured
|
||||||
time cargo test $features_test "tests::windows::$test_filter" -- --test-threads=1
|
time cargo test $features_test "tests::windows::$test_filter"
|
||||||
RES=$?
|
RES=$?
|
||||||
|
|
||||||
dmsetup remove_all -f
|
dmsetup remove_all -f
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ if [ ! -f "$BIONIC_OS_RAW_IMAGE" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
FOCAL_OS_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210407-0.qcow2"
|
FOCAL_OS_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.qcow2"
|
||||||
FOCAL_OS_IMAGE_URL="https://cloudhypervisorstorage.blob.core.windows.net/images/$FOCAL_OS_IMAGE_NAME"
|
FOCAL_OS_IMAGE_URL="https://cloudhypervisorstorage.blob.core.windows.net/images/$FOCAL_OS_IMAGE_NAME"
|
||||||
FOCAL_OS_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME"
|
FOCAL_OS_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME"
|
||||||
if [ ! -f "$FOCAL_OS_IMAGE" ]; then
|
if [ ! -f "$FOCAL_OS_IMAGE" ]; then
|
||||||
@@ -52,7 +52,7 @@ if [ ! -f "$FOCAL_OS_IMAGE" ]; then
|
|||||||
popd
|
popd
|
||||||
fi
|
fi
|
||||||
|
|
||||||
FOCAL_OS_RAW_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210407-0.raw"
|
FOCAL_OS_RAW_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.raw"
|
||||||
FOCAL_OS_RAW_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_RAW_IMAGE_NAME"
|
FOCAL_OS_RAW_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_RAW_IMAGE_NAME"
|
||||||
if [ ! -f "$FOCAL_OS_RAW_IMAGE" ]; then
|
if [ ! -f "$FOCAL_OS_RAW_IMAGE" ]; then
|
||||||
pushd $WORKLOADS_DIR
|
pushd $WORKLOADS_DIR
|
||||||
@@ -96,7 +96,6 @@ popd
|
|||||||
|
|
||||||
# Build custom kernel based on virtio-pmem and virtio-fs upstream patches
|
# Build custom kernel based on virtio-pmem and virtio-fs upstream patches
|
||||||
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
|
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
|
||||||
BZIMAGE_IMAGE="$WORKLOADS_DIR/bzImage"
|
|
||||||
|
|
||||||
LINUX_CUSTOM_DIR="$WORKLOADS_DIR/linux-custom"
|
LINUX_CUSTOM_DIR="$WORKLOADS_DIR/linux-custom"
|
||||||
|
|
||||||
@@ -112,7 +111,6 @@ if [ ! -f "$VMLINUX_IMAGE" ]; then
|
|||||||
pushd $LINUX_CUSTOM_DIR
|
pushd $LINUX_CUSTOM_DIR
|
||||||
time make bzImage -j `nproc`
|
time make bzImage -j `nproc`
|
||||||
cp vmlinux $VMLINUX_IMAGE || exit 1
|
cp vmlinux $VMLINUX_IMAGE || exit 1
|
||||||
cp arch/x86/boot/bzImage $BZIMAGE_IMAGE || exit 1
|
|
||||||
popd
|
popd
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -200,10 +198,16 @@ sudo bash -c "echo 1000000 > /sys/kernel/mm/ksm/pages_to_scan"
|
|||||||
sudo bash -c "echo 10 > /sys/kernel/mm/ksm/sleep_millisecs"
|
sudo bash -c "echo 10 > /sys/kernel/mm/ksm/sleep_millisecs"
|
||||||
sudo bash -c "echo 1 > /sys/kernel/mm/ksm/run"
|
sudo bash -c "echo 1 > /sys/kernel/mm/ksm/run"
|
||||||
|
|
||||||
# test_vfio relies on hugepages
|
# Both test_vfio and ovs-dpdk rely on hugepages
|
||||||
echo 4096 | sudo tee /proc/sys/vm/nr_hugepages
|
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
|
||||||
sudo chmod a+rwX /dev/hugepages
|
sudo chmod a+rwX /dev/hugepages
|
||||||
|
|
||||||
|
# Setup ovs-dpdk
|
||||||
|
service openvswitch-switch start
|
||||||
|
ovs-vsctl init
|
||||||
|
ovs-vsctl set Open_vSwitch . other_config:dpdk-init=true
|
||||||
|
service openvswitch-switch restart
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
time cargo test $features_test "tests::parallel::$test_filter"
|
time cargo test $features_test "tests::parallel::$test_filter"
|
||||||
RES=$?
|
RES=$?
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
6fee67adbfed8db7a225be23ee9d90b5bd7f19e6 bionic-server-cloudimg-arm64.img
|
6fee67adbfed8db7a225be23ee9d90b5bd7f19e6 bionic-server-cloudimg-arm64.img
|
||||||
786fe1c33588334e92b35c65e414da068df180bc bionic-server-cloudimg-arm64.raw
|
786fe1c33588334e92b35c65e414da068df180bc bionic-server-cloudimg-arm64.raw
|
||||||
34039f2fc4242acff0d42af82fbee91070978da3 bionic-server-cloudimg-arm64.qcow2
|
6e66f9f4b01adc72c884c1c1111e60afadc9c871 bionic-server-cloudimg-arm64.qcow2
|
||||||
e4addb6e212a298144f9eb0eb6e36019d013f0e7 alpine-minirootfs-aarch64.tar.gz
|
e4addb6e212a298144f9eb0eb6e36019d013f0e7 alpine-minirootfs-aarch64.tar.gz
|
||||||
063d1a9f32db641138e6e0c53f58e6545a3d48e6 focal-server-cloudimg-arm64-custom.raw
|
063d1a9f32db641138e6e0c53f58e6545a3d48e6 focal-server-cloudimg-arm64-custom.raw
|
||||||
013837926872f1c7d1b3a1a95305e4a31c8600ab focal-server-cloudimg-arm64-custom.qcow2
|
013837926872f1c7d1b3a1a95305e4a31c8600ab focal-server-cloudimg-arm64-custom.qcow2
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
27f3b17962ace69b51f0ddc2012095e3109e6ed8 bionic-server-cloudimg-amd64.qcow2
|
27f3b17962ace69b51f0ddc2012095e3109e6ed8 bionic-server-cloudimg-amd64.qcow2
|
||||||
8db9cc58b01452ce2d06c313177e6e74d8582d93 bionic-server-cloudimg-amd64.raw
|
8db9cc58b01452ce2d06c313177e6e74d8582d93 bionic-server-cloudimg-amd64.raw
|
||||||
d4a44acc6014d5f83dea1c625c43d677a95fa75f alpine-minirootfs-x86_64.tar.gz
|
d4a44acc6014d5f83dea1c625c43d677a95fa75f alpine-minirootfs-x86_64.tar.gz
|
||||||
f2f88ab4c08e36a4b6747a1aac4f94065952cadd focal-server-cloudimg-amd64-custom-20210407-0.qcow2
|
f1eccdc5e1b515dbad294426ab081b47ebfb97c0 focal-server-cloudimg-amd64-custom-20210609-0.qcow2
|
||||||
6c5770ebd34c0dd53987bc9deae43690ef02ffc5 focal-server-cloudimg-amd64-custom-20210407-0.raw
|
7f5a8358243a96adf61f5c20139b29f308f2c0e3 focal-server-cloudimg-amd64-custom-20210609-0.raw
|
||||||
|
|||||||
@@ -5,9 +5,6 @@
|
|||||||
|
|
||||||
#[macro_use(crate_authors)]
|
#[macro_use(crate_authors)]
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
extern crate api_client;
|
|
||||||
extern crate serde_json;
|
|
||||||
extern crate vmm;
|
|
||||||
|
|
||||||
use api_client::simple_api_command;
|
use api_client::simple_api_command;
|
||||||
use api_client::Error as ApiClientError;
|
use api_client::Error as ApiClientError;
|
||||||
|
|||||||
39
src/main.rs
39
src/main.rs
@@ -3,14 +3,8 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
//
|
//
|
||||||
|
|
||||||
extern crate anyhow;
|
|
||||||
extern crate signal_hook;
|
|
||||||
extern crate vmm;
|
|
||||||
extern crate vmm_sys_util;
|
|
||||||
|
|
||||||
#[macro_use(crate_authors)]
|
#[macro_use(crate_authors)]
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate event_monitor;
|
extern crate event_monitor;
|
||||||
|
|
||||||
@@ -194,7 +188,7 @@ fn create_app<'a, 'b>(
|
|||||||
.long("kernel")
|
.long("kernel")
|
||||||
.help(
|
.help(
|
||||||
"Path to loaded kernel. This may be a kernel or firmware that supports a PVH \
|
"Path to loaded kernel. This may be a kernel or firmware that supports a PVH \
|
||||||
entry point, a vmlinux ELF file or a Linux bzImage or achitecture equivalent",
|
entry point (e.g. vmlinux) or architecture equivalent",
|
||||||
)
|
)
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.group("vm-config"),
|
.group("vm-config"),
|
||||||
@@ -984,11 +978,13 @@ mod unit_tests {
|
|||||||
(
|
(
|
||||||
vec![
|
vec![
|
||||||
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
||||||
|
"--cpus", "boot=2",
|
||||||
"--net",
|
"--net",
|
||||||
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4,mask=5.6.7.8,num_queues=4",
|
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4,mask=5.6.7.8,num_queues=4",
|
||||||
],
|
],
|
||||||
r#"{
|
r#"{
|
||||||
"kernel": {"path": "/path/to/kernel"},
|
"kernel": {"path": "/path/to/kernel"},
|
||||||
|
"cpus": {"boot_vcpus": 2, "max_vcpus": 2},
|
||||||
"net": [
|
"net": [
|
||||||
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4", "mask": "5.6.7.8", "num_queues": 4}
|
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4", "mask": "5.6.7.8", "num_queues": 4}
|
||||||
]
|
]
|
||||||
@@ -998,11 +994,13 @@ mod unit_tests {
|
|||||||
(
|
(
|
||||||
vec![
|
vec![
|
||||||
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
||||||
|
"--cpus", "boot=2",
|
||||||
"--net",
|
"--net",
|
||||||
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4,mask=5.6.7.8,num_queues=4,queue_size=128",
|
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4,mask=5.6.7.8,num_queues=4,queue_size=128",
|
||||||
],
|
],
|
||||||
r#"{
|
r#"{
|
||||||
"kernel": {"path": "/path/to/kernel"},
|
"kernel": {"path": "/path/to/kernel"},
|
||||||
|
"cpus": {"boot_vcpus": 2, "max_vcpus": 2},
|
||||||
"net": [
|
"net": [
|
||||||
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4", "mask": "5.6.7.8", "num_queues": 4, "queue_size": 128}
|
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4", "mask": "5.6.7.8", "num_queues": 4, "queue_size": 128}
|
||||||
]
|
]
|
||||||
@@ -1163,13 +1161,14 @@ mod unit_tests {
|
|||||||
(
|
(
|
||||||
vec![
|
vec![
|
||||||
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
||||||
"--memory", "shared=true",
|
"--memory", "shared=true", "--cpus", "boot=4",
|
||||||
"--fs",
|
"--fs",
|
||||||
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4",
|
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4",
|
||||||
],
|
],
|
||||||
r#"{
|
r#"{
|
||||||
"kernel": {"path": "/path/to/kernel"},
|
"kernel": {"path": "/path/to/kernel"},
|
||||||
"memory" : { "shared": true, "size": 536870912 },
|
"memory" : { "shared": true, "size": 536870912 },
|
||||||
|
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
|
||||||
"fs": [
|
"fs": [
|
||||||
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4}
|
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4}
|
||||||
]
|
]
|
||||||
@@ -1179,13 +1178,14 @@ mod unit_tests {
|
|||||||
(
|
(
|
||||||
vec![
|
vec![
|
||||||
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
||||||
"--memory", "shared=true",
|
"--memory", "shared=true", "--cpus", "boot=4",
|
||||||
"--fs",
|
"--fs",
|
||||||
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128"
|
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128"
|
||||||
],
|
],
|
||||||
r#"{
|
r#"{
|
||||||
"kernel": {"path": "/path/to/kernel"},
|
"kernel": {"path": "/path/to/kernel"},
|
||||||
"memory" : { "shared": true, "size": 536870912 },
|
"memory" : { "shared": true, "size": 536870912 },
|
||||||
|
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
|
||||||
"fs": [
|
"fs": [
|
||||||
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128}
|
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128}
|
||||||
]
|
]
|
||||||
@@ -1195,13 +1195,14 @@ mod unit_tests {
|
|||||||
(
|
(
|
||||||
vec![
|
vec![
|
||||||
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
||||||
"--memory", "shared=true",
|
"--memory", "shared=true", "--cpus", "boot=4",
|
||||||
"--fs",
|
"--fs",
|
||||||
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,dax=on"
|
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,dax=on"
|
||||||
],
|
],
|
||||||
r#"{
|
r#"{
|
||||||
"kernel": {"path": "/path/to/kernel"},
|
"kernel": {"path": "/path/to/kernel"},
|
||||||
"memory" : { "shared": true, "size": 536870912 },
|
"memory" : { "shared": true, "size": 536870912 },
|
||||||
|
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
|
||||||
"fs": [
|
"fs": [
|
||||||
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128}
|
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128}
|
||||||
]
|
]
|
||||||
@@ -1211,13 +1212,14 @@ mod unit_tests {
|
|||||||
(
|
(
|
||||||
vec![
|
vec![
|
||||||
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
||||||
"--memory", "shared=true",
|
"--memory", "shared=true", "--cpus", "boot=4",
|
||||||
"--fs",
|
"--fs",
|
||||||
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,dax=on"
|
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,dax=on"
|
||||||
],
|
],
|
||||||
r#"{
|
r#"{
|
||||||
"kernel": {"path": "/path/to/kernel"},
|
"kernel": {"path": "/path/to/kernel"},
|
||||||
"memory" : { "shared": true, "size": 536870912 },
|
"memory" : { "shared": true, "size": 536870912 },
|
||||||
|
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
|
||||||
"fs": [
|
"fs": [
|
||||||
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128, "dax": true}
|
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128, "dax": true}
|
||||||
]
|
]
|
||||||
@@ -1227,13 +1229,14 @@ mod unit_tests {
|
|||||||
(
|
(
|
||||||
vec![
|
vec![
|
||||||
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
||||||
"--memory", "shared=true",
|
"--memory", "shared=true", "--cpus", "boot=4",
|
||||||
"--fs",
|
"--fs",
|
||||||
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128"
|
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128"
|
||||||
],
|
],
|
||||||
r#"{
|
r#"{
|
||||||
"kernel": {"path": "/path/to/kernel"},
|
"kernel": {"path": "/path/to/kernel"},
|
||||||
"memory" : { "shared": true, "size": 536870912 },
|
"memory" : { "shared": true, "size": 536870912 },
|
||||||
|
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
|
||||||
"fs": [
|
"fs": [
|
||||||
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128, "dax": true}
|
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128, "dax": true}
|
||||||
]
|
]
|
||||||
@@ -1243,13 +1246,14 @@ mod unit_tests {
|
|||||||
(
|
(
|
||||||
vec![
|
vec![
|
||||||
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
||||||
"--memory", "shared=true",
|
"--memory", "shared=true", "--cpus", "boot=4",
|
||||||
"--fs",
|
"--fs",
|
||||||
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,cache_size=8589934592"
|
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,cache_size=8589934592"
|
||||||
],
|
],
|
||||||
r#"{
|
r#"{
|
||||||
"kernel": {"path": "/path/to/kernel"},
|
"kernel": {"path": "/path/to/kernel"},
|
||||||
"memory" : { "shared": true, "size": 536870912 },
|
"memory" : { "shared": true, "size": 536870912 },
|
||||||
|
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
|
||||||
"fs": [
|
"fs": [
|
||||||
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128}
|
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128}
|
||||||
]
|
]
|
||||||
@@ -1259,13 +1263,14 @@ mod unit_tests {
|
|||||||
(
|
(
|
||||||
vec![
|
vec![
|
||||||
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
||||||
"--memory", "shared=true",
|
"--memory", "shared=true", "--cpus", "boot=4",
|
||||||
"--fs",
|
"--fs",
|
||||||
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128"
|
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128"
|
||||||
],
|
],
|
||||||
r#"{
|
r#"{
|
||||||
"kernel": {"path": "/path/to/kernel"},
|
"kernel": {"path": "/path/to/kernel"},
|
||||||
"memory" : { "shared": true, "size": 536870912 },
|
"memory" : { "shared": true, "size": 536870912 },
|
||||||
|
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
|
||||||
"fs": [
|
"fs": [
|
||||||
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128, "cache_size": 8589934592}
|
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128, "cache_size": 8589934592}
|
||||||
]
|
]
|
||||||
@@ -1275,13 +1280,14 @@ mod unit_tests {
|
|||||||
(
|
(
|
||||||
vec![
|
vec![
|
||||||
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
||||||
"--memory", "shared=true",
|
"--memory", "shared=true","--cpus", "boot=4",
|
||||||
"--fs",
|
"--fs",
|
||||||
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,cache_size=4294967296"
|
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,cache_size=4294967296"
|
||||||
],
|
],
|
||||||
r#"{
|
r#"{
|
||||||
"kernel": {"path": "/path/to/kernel"},
|
"kernel": {"path": "/path/to/kernel"},
|
||||||
"memory" : { "shared": true, "size": 536870912 },
|
"memory" : { "shared": true, "size": 536870912 },
|
||||||
|
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
|
||||||
"fs": [
|
"fs": [
|
||||||
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128, "cache_size": 4294967296}
|
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128, "cache_size": 4294967296}
|
||||||
]
|
]
|
||||||
@@ -1291,13 +1297,14 @@ mod unit_tests {
|
|||||||
(
|
(
|
||||||
vec![
|
vec![
|
||||||
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
||||||
"--memory", "shared=true",
|
"--memory", "shared=true","--cpus", "boot=4",
|
||||||
"--fs",
|
"--fs",
|
||||||
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,cache_size=4294967296"
|
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,cache_size=4294967296"
|
||||||
],
|
],
|
||||||
r#"{
|
r#"{
|
||||||
"kernel": {"path": "/path/to/kernel"},
|
"kernel": {"path": "/path/to/kernel"},
|
||||||
"memory" : { "shared": true, "size": 536870912 },
|
"memory" : { "shared": true, "size": 536870912 },
|
||||||
|
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
|
||||||
"fs": [
|
"fs": [
|
||||||
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128}
|
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ write_files:
|
|||||||
# 1G ram requires 512 pages
|
# 1G ram requires 512 pages
|
||||||
echo 512 | sudo tee /proc/sys/vm/nr_hugepages
|
echo 512 | sudo tee /proc/sys/vm/nr_hugepages
|
||||||
sudo chmod a+rwX /dev/hugepages
|
sudo chmod a+rwX /dev/hugepages
|
||||||
/mnt/cloud-hypervisor --kernel /mnt/vmlinux --cmdline "console=hvc0 reboot=k panic=1 nomodules root=/dev/vda1 VFIOTAG" --disk path=/mnt/focal-server-cloudimg-amd64-custom-20210407-0.qcow2 path=/mnt/cloudinit.img --cpus boot=1 --memory size=512M,hotplug_size=1G,hugepages=on --device path=/sys/bus/pci/devices/0000:00:06.0/ path=/sys/bus/pci/devices/0000:00:07.0/ --api-socket /tmp/ch_api.sock
|
/mnt/cloud-hypervisor --kernel /mnt/vmlinux --cmdline "console=hvc0 reboot=k panic=1 nomodules root=/dev/vda1 VFIOTAG" --disk path=/mnt/focal-server-cloudimg-amd64-custom-20210609-0.qcow2 path=/mnt/cloudinit.img --cpus boot=1 --memory size=512M,hotplug_size=1G,hugepages=on --device path=/sys/bus/pci/devices/0000:00:06.0/ path=/sys/bus/pci/devices/0000:00:07.0/ --api-socket /tmp/ch_api.sock
|
||||||
|
|
||||||
-
|
-
|
||||||
path: /etc/systemd/system/notify-booted.service
|
path: /etc/systemd/system/notify-booted.service
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use std::net::TcpListener;
|
|||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::process::{ExitStatus, Output};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use vmm_sys_util::tempdir::TempDir;
|
use vmm_sys_util::tempdir::TempDir;
|
||||||
@@ -503,6 +504,8 @@ pub enum SshCommandError {
|
|||||||
Authentication(ssh2::Error),
|
Authentication(ssh2::Error),
|
||||||
ChannelSession(ssh2::Error),
|
ChannelSession(ssh2::Error),
|
||||||
Command(ssh2::Error),
|
Command(ssh2::Error),
|
||||||
|
ExitStatus(ssh2::Error),
|
||||||
|
NonZeroExitStatus(i32),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ssh_command_ip_with_auth(
|
pub fn ssh_command_ip_with_auth(
|
||||||
@@ -537,7 +540,14 @@ pub fn ssh_command_ip_with_auth(
|
|||||||
let _ = channel.read_to_string(&mut s);
|
let _ = channel.read_to_string(&mut s);
|
||||||
let _ = channel.close();
|
let _ = channel.close();
|
||||||
let _ = channel.wait_close();
|
let _ = channel.wait_close();
|
||||||
Ok(())
|
|
||||||
|
let status = channel.exit_status().map_err(SshCommandError::ExitStatus)?;
|
||||||
|
|
||||||
|
if status != 0 {
|
||||||
|
Err(SshCommandError::NonZeroExitStatus(status))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
})() {
|
})() {
|
||||||
Ok(_) => break,
|
Ok(_) => break,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@@ -580,3 +590,17 @@ pub fn ssh_command_ip(
|
|||||||
timeout,
|
timeout,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn exec_host_command_status(command: &str) -> ExitStatus {
|
||||||
|
std::process::Command::new("bash")
|
||||||
|
.args(&["-c", command])
|
||||||
|
.status()
|
||||||
|
.expect(&format!("Expected '{}' to run", command))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exec_host_command_output(command: &str) -> Output {
|
||||||
|
std::process::Command::new("bash")
|
||||||
|
.args(&["-c", command])
|
||||||
|
.output()
|
||||||
|
.expect(&format!("Expected '{}' to run", command))
|
||||||
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user