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; } message CpuidEntry { uint32 function = 1; bool has_index = 3; uint32 index = 4; uint32 eax = 5; uint32 ebx = 6; uint32 ecx = 7; uint32 edx = 8; } // 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; // Must be true for the MemoryDirtyLog method to work on this object. bool dirty_log = 5; } 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 CheckExtension { uint32 extension = 1; } message CpuidRequest { } message MsrListRequest { } message GetNetConfig {} message ReserveRange { AddressSpace space = 1; uint64 start = 2; uint64 length = 3; bool async_write = 4; } 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; } // Each type refers to certain piece of VM state (such as PIT state). // The structure of the data corresponds to the kvm structure. enum StateSet { // struct kvm_pic_state PIC0 = 0; // struct kvm_pic_state PIC1 = 1; // struct kvm_ioapic_state IOAPIC = 2; // struct kvm_pit_state2 PIT = 3; // struct kvm_clock_data CLOCK = 4; } message GetState { StateSet set = 1; } message SetState { StateSet set = 1; // The in memory representation of certain state, depending on the value // of the StateSet. bytes state = 2; } message SetIdentityMapAddr { uint32 address = 1; } message PauseVcpus { uint64 cpu_mask = 1; uint64 user = 2; } message GetVcpus {} message Start {} message SetCallHint { message RegHint { bool match_rax = 1; bool match_rbx = 2; bool match_rcx = 3; bool match_rdx = 4; uint64 rax = 5; uint64 rbx = 6; uint64 rcx = 7; uint64 rdx = 8; bool send_sregs = 9; bool send_debugregs = 10; } AddressSpace space = 1; uint64 address = 2; bool on_write = 3; repeated RegHint hints = 4; } 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; CheckExtension check_extension = 5; CpuidRequest get_supported_cpuid = 6; CpuidRequest get_emulated_cpuid = 7; MsrListRequest get_msr_index_list = 8; GetNetConfig get_net_config = 9; ReserveRange reserve_range = 10; SetIrq set_irq = 11; SetIrqRouting set_irq_routing = 12; GetState get_state = 13; SetState set_state = 14; SetIdentityMapAddr set_identity_map_addr = 15; PauseVcpus pause_vcpus = 16; GetVcpus get_vcpus = 17; Start start = 18; SetCallHint set_call_hint = 19; // Method for a Memory type object for retrieving the dirty bitmap. Only valid if the memory // object was created with dirty_log set. 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 CheckExtension { bool has_extension = 1; } message CpuidResponse { repeated CpuidEntry entries = 1; } message MsrListResponse { repeated uint32 indices = 1; } // GetNetConfig messages also return a file descriptor for the tap device. message GetNetConfig { bytes host_mac_address = 1; fixed32 host_ipv4_address = 2; fixed32 netmask = 3; } message ReserveRange {} message SetIrq {} message SetIrqRouting {} message GetState { // The in memory representation of a state, depending on what StateSet was // requested in GetState. bytes state = 1; } message SetState {} 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 SetCallHint {} 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; CheckExtension check_extension = 6; CpuidResponse get_supported_cpuid = 7; CpuidResponse get_emulated_cpuid = 8; MsrListResponse get_msr_index_list = 9; GetNetConfig get_net_config = 10; ReserveRange reserve_range = 11; SetIrq set_irq = 12; SetIrqRouting set_irq_routing = 13; GetState get_state = 14; SetState set_state = 15; SetIdentityMapAddr set_identity_map_addr = 16; PauseVcpus pause_vcpus = 17; GetVcpus get_vcpus = 18; Start start = 19; SetCallHint set_call_hint = 20; 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; // The following tracks what deferred set calls to apply. bytes regs = 2; bytes sregs = 3; bytes debugregs = 4; } // Each type refers to certain piece of VCPU state (a set registers, or something else). // 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; // struct kvm_debugregs DEBUGREGS = 3; // struct kvm_lapic_state LAPIC = 4; // struct kvm_mp_state MP = 5; // struct kvm_xcrs XCREGS = 6; // struct kvm_vcpu_events EVENTS = 7; } message GetState { StateSet set = 1; } message SetState { StateSet set = 1; // The in memory representation of a struct kvm_regs, struct kvm_sregs, // struct kvm_fpu, struct kvm_debugregs, struct kvm_lapic_state, // struct kvm_mp_state, struct kvm_xcrs or struct kvm_vcpu_events // depending on the value of the StateSet. bytes state = 2; } message CpuidRequest { } message GetMsrs { // The entry data will be returned in the same order as this in the // VcpuResponse::GetMsrs::entry_data array. repeated uint32 entry_indices = 1; } message MsrEntry { uint32 index = 1; uint64 data = 2; } message SetMsrs { repeated MsrEntry entries = 1; } message SetCpuid { repeated CpuidEntry entries = 1; } message Shutdown { } message EnableCapability { uint32 capability = 1; } // 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; GetMsrs get_msrs = 5; SetMsrs set_msrs = 6; SetCpuid set_cpuid = 7; Shutdown shutdown = 8; CpuidRequest get_hyperv_cpuid = 9; EnableCapability enable_capability = 10; } } 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; bool no_resume = 4; bytes data = 5; // The following can be eagerly provided. bytes regs = 6; bytes sregs = 7; bytes debugregs = 8; } // This type of wait reason is only generated after a PauseVcpus request on this VCPU. message User { uint64 user = 1; } message HypervCall { uint64 input = 1; uint64 params0 = 2; uint64 params1 = 3; } message HypervSynic { uint32 msr = 1; uint64 control = 2; uint64 evt_page = 3; uint64 msg_page = 4; } oneof exit { Init init = 1; Io io = 2; User user = 3; HypervCall hyperv_call = 4; HypervSynic hyperv_synic = 5; } } message GetState { // The in memory representation of a struct kvm_regs, struct kvm_sregs, // struct kvm_fpu, struct kvm_debugregs, struct kvm_lapic_state, // struct kvm_mp_state, struct kvm_xcrs or struct kvm_vcpu_events // depending on the value of the StateSet. bytes state = 1; } message SetState { } message CpuidResponse { repeated CpuidEntry entries = 1; } message GetMsrs { // The order of the entry_data values is the same order as the array of indices given in the // corresponding request. repeated uint64 entry_data = 1; } message SetMsrs {} message SetCpuid {} message EnableCapability {} // 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 was 3 but no longer gets a reply. GetState get_state = 4; SetState set_state = 5; GetMsrs get_msrs = 6; SetMsrs set_msrs = 7; SetCpuid set_cpuid = 8; CpuidResponse get_hyperv_cpuid = 9; EnableCapability enable_capability = 10; } }