diff options
Diffstat (limited to 'crosvm_plugin/src/lib.rs')
-rw-r--r-- | crosvm_plugin/src/lib.rs | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/crosvm_plugin/src/lib.rs b/crosvm_plugin/src/lib.rs index eb30e4b..05c19bf 100644 --- a/crosvm_plugin/src/lib.rs +++ b/crosvm_plugin/src/lib.rs @@ -59,6 +59,8 @@ const CROSVM_IRQ_ROUTE_MSI: u32 = 1; const CROSVM_VCPU_EVENT_KIND_INIT: u32 = 0; const CROSVM_VCPU_EVENT_KIND_IO_ACCESS: u32 = 1; const CROSVM_VCPU_EVENT_KIND_PAUSED: u32 = 2; +const CROSVM_VCPU_EVENT_KIND_HYPERV_HCALL: u32 = 3; +const CROSVM_VCPU_EVENT_KIND_HYPERV_SYNIC: u32 = 4; #[repr(C)] #[derive(Copy, Clone)] @@ -166,8 +168,11 @@ pub enum Stat { DestroyConnection, GetShutdownEventFd, CheckExtentsion, + EnableVmCapability, + EnableVcpuCapability, GetSupportedCpuid, GetEmulatedCpuid, + GetHypervCpuid, GetMsrIndexList, NetGetConfig, ReserveRange, @@ -922,10 +927,30 @@ struct anon_io_access { __reserved1: [u8; 2], } +#[derive(Copy, Clone)] +#[repr(C)] +struct anon_hyperv_call { + input: u64, + result: *mut u8, + params: [u64; 2], +} + +#[derive(Copy, Clone)] +#[repr(C)] +struct anon_hyperv_synic { + msr: u32, + reserved: u32, + control: u64, + evt_page: u64, + msg_page: u64, +} + #[repr(C)] union anon_vcpu_event { io_access: anon_io_access, user: *mut c_void, + hyperv_call: anon_hyperv_call, + hyperv_synic: anon_hyperv_synic, #[allow(dead_code)] __reserved: [u8; 64], } @@ -1115,6 +1140,33 @@ impl crosvm_vcpu { self.sregs.get = false; self.debugregs.get = false; Ok(()) + } else if wait.has_hyperv_call() { + let hv: &VcpuResponse_Wait_HypervCall = wait.get_hyperv_call(); + event.kind = CROSVM_VCPU_EVENT_KIND_HYPERV_HCALL; + self.resume_data = vec![0; 8]; + event.event.hyperv_call = anon_hyperv_call { + input: hv.input, + result: self.resume_data.as_mut_ptr(), + params: [hv.params0, hv.params1], + }; + self.regs.get = false; + self.sregs.get = false; + self.debugregs.get = false; + Ok(()) + } else if wait.has_hyperv_synic() { + let hv: &VcpuResponse_Wait_HypervSynic = wait.get_hyperv_synic(); + event.kind = CROSVM_VCPU_EVENT_KIND_HYPERV_SYNIC; + event.event.hyperv_synic = anon_hyperv_synic { + msr: hv.msr, + reserved: 0, + control: hv.control, + evt_page: hv.evt_page, + msg_page: hv.msg_page, + }; + self.regs.get = false; + self.sregs.get = false; + self.debugregs.get = false; + Ok(()) } else { Err(EPROTO) } @@ -1202,6 +1254,39 @@ impl crosvm_vcpu { Ok(()) } + fn get_hyperv_cpuid( + &mut self, + cpuid_entries: &mut [kvm_cpuid_entry2], + cpuid_count: &mut usize, + ) -> result::Result<(), c_int> { + *cpuid_count = 0; + + let mut r = VcpuRequest::new(); + r.mut_get_hyperv_cpuid(); + + let response = self.vcpu_transaction(&r)?; + if !response.has_get_hyperv_cpuid() { + return Err(EPROTO); + } + + let hyperv_cpuids: &VcpuResponse_CpuidResponse = response.get_get_hyperv_cpuid(); + + *cpuid_count = hyperv_cpuids.get_entries().len(); + if *cpuid_count > cpuid_entries.len() { + return Err(E2BIG); + } + + for (proto_entry, kvm_entry) in hyperv_cpuids + .get_entries() + .iter() + .zip(cpuid_entries.iter_mut()) + { + *kvm_entry = cpuid_proto_to_kvm(proto_entry); + } + + Ok(()) + } + fn get_msrs( &mut self, msr_entries: &mut [kvm_msr_entry], @@ -1255,6 +1340,13 @@ impl crosvm_vcpu { self.vcpu_transaction(&r)?; Ok(()) } + + fn enable_capability(&mut self, capability: u32) -> result::Result<(), c_int> { + let mut r = VcpuRequest::new(); + r.mut_enable_capability().capability = capability; + self.vcpu_transaction(&r)?; + Ok(()) + } } // crosvm API signals success as 0 and errors as negative values @@ -1337,6 +1429,17 @@ pub unsafe extern "C" fn crosvm_check_extension( } #[no_mangle] +pub unsafe extern "C" fn crosvm_enable_capability( + _self_: *mut crosvm, + _capability: u32, + _flags: u32, + _args: *const u64, +) -> c_int { + let _u = record(Stat::EnableVmCapability); + -EINVAL +} + +#[no_mangle] pub unsafe extern "C" fn crosvm_get_supported_cpuid( this: *mut crosvm, entry_count: u32, @@ -1804,6 +1907,22 @@ pub unsafe extern "C" fn crosvm_vcpu_set_xcrs( } #[no_mangle] +pub unsafe extern "C" fn crosvm_get_hyperv_cpuid( + this: *mut crosvm_vcpu, + entry_count: u32, + cpuid_entries: *mut kvm_cpuid_entry2, + out_count: *mut u32, +) -> c_int { + let _u = record(Stat::GetHypervCpuid); + let this = &mut *this; + let cpuid_entries = from_raw_parts_mut(cpuid_entries, entry_count as usize); + let mut cpuid_count: usize = 0; + let ret = this.get_hyperv_cpuid(cpuid_entries, &mut cpuid_count); + *out_count = cpuid_count as u32; + to_crosvm_rc(ret) +} + +#[no_mangle] pub unsafe extern "C" fn crosvm_vcpu_get_msrs( this: *mut crosvm_vcpu, msr_count: u32, @@ -1846,6 +1965,25 @@ pub unsafe extern "C" fn crosvm_vcpu_set_cpuid( } #[no_mangle] +pub unsafe extern "C" fn crosvm_vcpu_enable_capability( + this: *mut crosvm_vcpu, + capability: u32, + flags: u32, + args: *const u64, +) -> c_int { + let _u = record(Stat::EnableVcpuCapability); + let this = &mut *this; + let args = slice::from_raw_parts(args, 4); + + if flags != 0 || args.iter().any(|v| *v != 0) { + return -EINVAL; + } + + let ret = this.enable_capability(capability); + to_crosvm_rc(ret) +} + +#[no_mangle] pub unsafe extern "C" fn crosvm_vcpu_get_lapic_state( this: *mut crosvm_vcpu, state: *mut kvm_lapic_state, |