add plugin_proto crate

This module defines the protocol shared between the crosvm plugin
process and main crosvm process.

TEST=cargo build --features plugin
BUG=chromium:800626
CQ-DEPEND=CL:892048

Change-Id: I5dfbe845644b7489f1918cecfcc07f28a223aa42
Reviewed-on: https://chromium-review.googlesource.com/869355
Commit-Ready: Zach Reizner <zachr@chromium.org>
Tested-by: Zach Reizner <zachr@chromium.org>
Reviewed-by: Zach Reizner <zachr@chromium.org>
This commit is contained in:
Zach Reizner 2018-01-16 17:35:27 -08:00 committed by chrome-bot
parent fc44d8059b
commit e0983c7625
6 changed files with 417 additions and 12 deletions

116
Cargo.lock generated
View file

@ -1,8 +1,30 @@
[root]
name = "x86_64"
version = "0.1.0"
dependencies = [
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"data_model 0.1.0",
"kvm 0.1.0",
"kvm_sys 0.1.0",
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"sys_util 0.1.0",
]
[[package]]
name = "bitflags"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "crosvm"
version = "0.1.0"
@ -14,6 +36,7 @@ dependencies = [
"kernel_loader 0.1.0",
"kvm 0.1.0",
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"plugin_proto 0.5.0",
"qcow 0.1.0",
"sys_util 0.1.0",
"vm_control 0.1.0",
@ -40,6 +63,20 @@ dependencies = [
"vm_control 0.1.0",
]
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "gcc"
version = "0.3.54"
@ -82,6 +119,14 @@ name = "libc"
version = "0.2.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "log"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "net_sys"
version = "0.1.0"
@ -98,6 +143,38 @@ dependencies = [
"sys_util 0.1.0",
]
[[package]]
name = "plugin_proto"
version = "0.5.0"
dependencies = [
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
"protobuf 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"protoc-rust 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "protobuf"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "protoc"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "protoc-rust"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"protobuf 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"protoc 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "qcow"
version = "0.1.0"
@ -107,6 +184,15 @@ dependencies = [
"sys_util 0.1.0",
]
[[package]]
name = "rand"
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "sys_util"
version = "0.1.0"
@ -121,6 +207,14 @@ dependencies = [
name = "syscall_defines"
version = "0.1.0"
[[package]]
name = "tempdir"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "vhost"
version = "0.1.0"
@ -149,19 +243,17 @@ dependencies = [
"sys_util 0.1.0",
]
[[package]]
name = "x86_64"
version = "0.1.0"
dependencies = [
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"data_model 0.1.0",
"kvm 0.1.0",
"kvm_sys 0.1.0",
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"sys_util 0.1.0",
]
[metadata]
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0"
"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
"checksum protobuf 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bec26e67194b7d991908145fdf21b7cae8b08423d96dcb9e860cd31f854b9506"
"checksum protoc 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5379c34ea2f9c69b99e6f25f6d0e6619876195ae7a3dcaf69f66bdb6c2e4dceb"
"checksum protoc-rust 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e211a7f56b2d020a59d483f652cfdfa6fd42e37bf544c0231e373807aa316c45"
"checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1"
"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"

View file

@ -9,6 +9,9 @@ panic = 'abort'
[workspace]
[features]
plugin = ["plugin_proto"]
[dependencies]
devices = { path = "devices" }
io_jail = { path = "io_jail" }
@ -20,6 +23,7 @@ byteorder = "=1.1.0"
vm_control = { path = "vm_control" }
data_model = { path = "data_model" }
qcow = { path = "qcow" }
plugin_proto = { path = "plugin_proto", optional = true }
[target.'cfg(target_arch = "x86_64")'.dependencies]
x86_64 = { path = "x86_64" }

12
plugin_proto/Cargo.toml Normal file
View file

@ -0,0 +1,12 @@
[package]
name = "plugin_proto"
version = "0.5.0"
authors = ["The Chromium OS Authors"]
build = "build.rs"
[dependencies]
protobuf = "=1.4.3"
[build-dependencies]
gcc = "=0.3.54"
protoc-rust = "=1.4.3"

27
plugin_proto/build.rs Normal file
View file

@ -0,0 +1,27 @@
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
extern crate protoc_rust;
use std::env;
use std::fs;
use std::io::Write;
use std::path::PathBuf;
fn main() {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
protoc_rust::run(protoc_rust::Args {
out_dir: out_dir.as_os_str().to_str().unwrap(),
input: &["protos/plugin.proto"],
includes: &["protos"],
})
.expect("protoc");
let mut mod_out = fs::File::create(out_dir.join("proto_include.rs")).unwrap();
writeln!(mod_out,
"#[path = \"{}\"] pub mod plugin_proto;\npub use plugin_proto::*;",
out_dir.join("plugin.rs").display())
.unwrap();
}

View file

@ -0,0 +1,268 @@
syntax = "proto3";
// The protocol defined here is actually two sub-protocols, one protocol for control of the main
// process (MainRequest/MainResponse), and one for control of each VCPU thread
// (VcpuRequest/VcpuResponse). Each protocol works the same: the client creates a protobuf of either
// a MainRequest or VcpuRequest, sends it encoded over the main socket or one of the vcpu sockets,
// reads the the MainResponse or VcpuResponse over the same socket and decodes it as a protobuf. For
// specific information on the purpose of each request, see the C API in crosvm.h. Most requests
// here map 1:1 to a function in that API. Only the intricacies unique to the wire protocol are
// commented on here.
enum AddressSpace {
IOPORT = 0;
MMIO = 1;
}
// A request made to the crosvm main process that affects the global aspects of the VM.
message MainRequest {
// Every message under the Create namespace will instantiate an object with the given ID. The
// type of object is determined by the oneof constructor field.
message Create {
message IoEvent {
AddressSpace space = 1;
uint64 address = 2;
uint32 length = 3;
uint64 datamatch = 4;
}
message Memory {
uint64 offset = 1;
uint64 start = 2;
uint64 length = 3;
bool read_only = 4;
}
message IrqEvent {
uint32 irq_id = 1;
bool resample = 2;
}
uint32 id = 1;
oneof constructor {
IoEvent io_event = 2;
// This message also requires a memfd sent over the socket.
Memory memory = 3;
IrqEvent irq_event = 4;
}
}
// No matter what the type an object is, it can be destroyed using this common method.
message Destroy {
uint32 id = 1;
}
message NewConnection {}
message GetShutdownEventfd {}
message ReserveRange {
AddressSpace space = 1;
uint64 start = 2;
uint64 length = 3;
}
message SetIrq {
uint32 irq_id = 1;
bool active = 2;
}
message SetIrqRouting {
message Route {
message Irqchip {
uint32 irqchip = 1;
uint32 pin = 2;
}
message Msi {
uint64 address = 1;
uint32 data = 2;
}
uint32 irq_id = 1;
oneof route {
Irqchip irqchip = 2;
Msi msi = 3;
}
}
repeated Route routes = 1;
}
message SetIdentityMapAddr {
uint32 address = 1;
}
message PauseVcpus {
uint64 cpu_mask = 1;
uint64 user = 2;
}
message GetVcpus {}
message Start {}
message MemoryDirtyLog {
uint32 id = 1;
}
// The type of the message is determined by which of these oneof fields is present in the
// protobuf.
oneof message {
// Common method for instantiating a new object of any type.
Create create = 1;
// Common method for destroying an object of any type.
Destroy destroy = 2;
NewConnection new_connection = 3;
GetShutdownEventfd get_shutdown_eventfd = 4;
ReserveRange reserve_range = 5;
SetIrq set_irq = 6;
SetIrqRouting set_irq_routing = 7;
SetIdentityMapAddr set_identity_map_addr = 8;
PauseVcpus pause_vcpus = 9;
GetVcpus get_vcpus = 10;
Start start = 11;
// Method for a Memory type object for retrieving the dirty bitmap.
MemoryDirtyLog dirty_log = 101;
}
}
message MainResponse {
// Depending on the object that was created, an fd might also come from the socket.
message Create {}
message Destroy {}
// NewMessage receives a socket fd along with the data from reading this socket.
// The returned socket can be used totally independently of the original socket, and can perform
// requests and responses independent of the other sockets.
message NewConnection {}
message GetShutdownEventfd {}
message ReserveRange {}
message SetIrq {}
message SetIrqRouting {}
message SetIdentityMapAddr {}
message PauseVcpus {}
// This message should also receive a socket fd per VCPU along with the data from reading this
// socket. The VcpuRequest/VcpuResponse protocol is run over each of the returned fds.
message GetVcpus {}
message Start {}
message MemoryDirtyLog {
bytes bitmap = 1;
}
// This is zero on success, and a negative integer on failure.
sint32 errno = 1;
// The field present here is always the same as the one present in the corresponding
// MainRequest.
oneof message {
Create create = 2;
Destroy destroy = 3;
NewConnection new_connection = 4;
GetShutdownEventfd get_shutdown_eventfd = 5;
ReserveRange reserve_range = 6;
SetIrq set_irq = 7;
SetIrqRouting set_irq_routing = 8;
SetIdentityMapAddr set_identity_map_addr = 9;
PauseVcpus pause_vcpus = 10;
GetVcpus get_vcpus = 11;
Start start = 12;
MemoryDirtyLog dirty_log = 101;
}
}
// A request made for a specific VCPU. These requests are sent over the sockets returned from the
// GetVcpu MainRequest.
message VcpuRequest {
// This message will block until a non-empty response can be sent. The first response will
// always be an Init wait reason.
message Wait {
}
message Resume {
// The data is only necessary for non-write (read) I/O accesses. In all other cases, data is
// ignored.
bytes data = 1;
}
// Each type refers to a set of KVM VCPU registers. The structure of the data corresponds to the
// kvm structure.
enum StateSet {
// struct kvm_regs
REGS = 0;
// struct kvm_sregs
SREGS = 1;
// struct kvm_fpu
FPU = 2;
}
message GetState {
StateSet set = 1;
}
message SetState {
StateSet set = 1;
// The in memory representation of a struct kvm_regs, struct kvm_sregs, or struct kvm_fpu,
// depending on the value of the StateSet.
bytes state = 2;
}
// The type of the message is determined by which of these oneof fields is present in the
// protobuf.
oneof message {
Wait wait = 1;
Resume resume = 2;
GetState get_state = 3;
SetState set_state = 4;
}
}
message VcpuResponse {
// Depending on the reason a VCPU has exited, the Wait request will unblock and return a field
// in the oneof exit. This is called the "wait reason."
message Wait {
// This request will always be the first wait reason returend by the first wait request.
message Init {
}
// This type of wait reason is only generated if the access occurred on this VCPU on an
// address previously reserved by a ReserveRange main request.
message Io {
AddressSpace space = 1;
uint64 address = 2;
bool is_write = 3;
bytes data = 4;
}
// This type of wait reason is only generated after a PuaseVcpus request on this VCPU.
message User {
uint64 user = 1;
}
oneof exit {
Init init = 1;
Io io = 2;
User user = 3;
}
}
message Resume {}
message GetState {
// The in memory representation of a struct kvm_regs, struct kvm_sregs, or struct kvm_fpu,
// depending on what StateSet was requested in GetState.
bytes state = 1;
}
message SetState {
}
// This is zero on success, and a negative integer on failure.
sint32 errno = 1;
// The field present here is always the same as the one present in the corresponding
// VcpuRequest.
oneof message {
Wait wait = 2;
Resume resume = 3;
GetState get_state = 4;
SetState set_state = 5;
}
}

2
plugin_proto/src/lib.rs Normal file
View file

@ -0,0 +1,2 @@
extern crate protobuf;
include!(concat!(env!("OUT_DIR"), "/proto_include.rs"));