summary refs log tree commit diff
path: root/plugin_proto
diff options
context:
space:
mode:
authorZach Reizner <zachr@google.com>2018-01-16 17:35:27 -0800
committerchrome-bot <chrome-bot@chromium.org>2018-01-30 17:47:17 -0800
commite0983c762535a6c82b1206d4857b17eb9803d38c (patch)
tree064ba884fc17b26deb31ca7294cb3dbcb00d444c /plugin_proto
parentfc44d8059b2333b7f49c1a11012eb6ca7d2250a5 (diff)
downloadcrosvm-e0983c762535a6c82b1206d4857b17eb9803d38c.tar
crosvm-e0983c762535a6c82b1206d4857b17eb9803d38c.tar.gz
crosvm-e0983c762535a6c82b1206d4857b17eb9803d38c.tar.bz2
crosvm-e0983c762535a6c82b1206d4857b17eb9803d38c.tar.lz
crosvm-e0983c762535a6c82b1206d4857b17eb9803d38c.tar.xz
crosvm-e0983c762535a6c82b1206d4857b17eb9803d38c.tar.zst
crosvm-e0983c762535a6c82b1206d4857b17eb9803d38c.zip
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>
Diffstat (limited to 'plugin_proto')
-rw-r--r--plugin_proto/Cargo.toml12
-rw-r--r--plugin_proto/build.rs27
-rw-r--r--plugin_proto/protos/plugin.proto268
-rw-r--r--plugin_proto/src/lib.rs2
4 files changed, 309 insertions, 0 deletions
diff --git a/plugin_proto/Cargo.toml b/plugin_proto/Cargo.toml
new file mode 100644
index 0000000..6fe8198
--- /dev/null
+++ b/plugin_proto/Cargo.toml
@@ -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"
diff --git a/plugin_proto/build.rs b/plugin_proto/build.rs
new file mode 100644
index 0000000..5e30fcd
--- /dev/null
+++ b/plugin_proto/build.rs
@@ -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();
+}
diff --git a/plugin_proto/protos/plugin.proto b/plugin_proto/protos/plugin.proto
new file mode 100644
index 0000000..aa959fc
--- /dev/null
+++ b/plugin_proto/protos/plugin.proto
@@ -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;
+    }
+}
diff --git a/plugin_proto/src/lib.rs b/plugin_proto/src/lib.rs
new file mode 100644
index 0000000..7f0d66c
--- /dev/null
+++ b/plugin_proto/src/lib.rs
@@ -0,0 +1,2 @@
+extern crate protobuf;
+include!(concat!(env!("OUT_DIR"), "/proto_include.rs"));