xref: /aosp_15_r20/external/crosvm/crosvm_plugin/src/lib.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2017 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #![cfg(any(target_os = "android", target_os = "linux"))]
6 #![cfg(target_arch = "x86_64")]
7 #![allow(non_camel_case_types)]
8 #![allow(clippy::missing_safety_doc)]
9 
10 //! This module implements the dynamically loaded client library API used by a crosvm plugin,
11 //! defined in `crosvm.h`. It implements the client half of the plugin protocol, which is defined in
12 //! the `protos::plugin` module.
13 //!
14 //! To implement the `crosvm.h` C API, each function and struct definition is repeated here, with
15 //! concrete definitions for each struct. Most functions are thin shims to the underlying object
16 //! oriented Rust implementation method. Most methods require a request over the crosvm connection,
17 //! which is done by creating a `MainRequest` or `VcpuRequest` protobuf and sending it over the
18 //! connection's socket. Then, that socket is read for a `MainResponse` or `VcpuResponse`, which is
19 //! translated to the appropriate return type for the C API.
20 
21 use std::env;
22 use std::fs::File;
23 use std::io::Read;
24 use std::io::Write;
25 use std::mem::size_of;
26 use std::mem::swap;
27 use std::os::raw::c_int;
28 use std::os::raw::c_void;
29 use std::os::unix::io::AsRawFd;
30 use std::os::unix::io::FromRawFd;
31 use std::os::unix::io::IntoRawFd;
32 use std::os::unix::io::RawFd;
33 use std::os::unix::net::UnixDatagram;
34 use std::ptr;
35 use std::ptr::null_mut;
36 use std::result;
37 use std::slice;
38 use std::slice::from_raw_parts;
39 use std::slice::from_raw_parts_mut;
40 use std::sync::atomic::AtomicUsize;
41 use std::sync::atomic::Ordering;
42 use std::sync::Arc;
43 
44 use base::ScmSocket;
45 use kvm::dirty_log_bitmap_size;
46 use kvm_sys::kvm_clock_data;
47 use kvm_sys::kvm_cpuid_entry2;
48 use kvm_sys::kvm_debugregs;
49 use kvm_sys::kvm_fpu;
50 use kvm_sys::kvm_ioapic_state;
51 use kvm_sys::kvm_lapic_state;
52 use kvm_sys::kvm_mp_state;
53 use kvm_sys::kvm_msr_entry;
54 use kvm_sys::kvm_pic_state;
55 use kvm_sys::kvm_pit_state2;
56 use kvm_sys::kvm_regs;
57 use kvm_sys::kvm_sregs;
58 use kvm_sys::kvm_vcpu_events;
59 use kvm_sys::kvm_xcrs;
60 use libc::E2BIG;
61 use libc::EINVAL;
62 use libc::ENOENT;
63 use libc::ENOTCONN;
64 use libc::EPROTO;
65 use protobuf::Enum;
66 use protobuf::Message;
67 use protos::plugin::*;
68 
69 #[cfg(feature = "stats")]
70 mod stats;
71 
72 // Needs to be large enough to receive all the VCPU sockets.
73 const MAX_DATAGRAM_FD: usize = 32;
74 // Needs to be large enough for a sizable dirty log.
75 const MAX_DATAGRAM_SIZE: usize = 0x40000;
76 
77 const CROSVM_IRQ_ROUTE_IRQCHIP: u32 = 0;
78 const CROSVM_IRQ_ROUTE_MSI: u32 = 1;
79 
80 const CROSVM_VCPU_EVENT_KIND_INIT: u32 = 0;
81 const CROSVM_VCPU_EVENT_KIND_IO_ACCESS: u32 = 1;
82 const CROSVM_VCPU_EVENT_KIND_PAUSED: u32 = 2;
83 const CROSVM_VCPU_EVENT_KIND_HYPERV_HCALL: u32 = 3;
84 const CROSVM_VCPU_EVENT_KIND_HYPERV_SYNIC: u32 = 4;
85 
86 pub const CROSVM_GPU_SERVER_FD_ENV: &str = "CROSVM_GPU_SERVER_FD";
87 pub const CROSVM_SOCKET_ENV: &str = "CROSVM_SOCKET";
88 #[cfg(feature = "stats")]
89 pub const CROSVM_STATS_ENV: &str = "CROSVM_STATS";
90 
91 #[repr(C)]
92 #[derive(Copy, Clone)]
93 pub struct crosvm_net_config {
94     tap_fd: c_int,
95     host_ipv4_address: u32,
96     netmask: u32,
97     host_mac_address: [u8; 6],
98     _reserved: [u8; 2],
99 }
100 
101 #[repr(C)]
102 #[derive(Copy, Clone)]
103 pub struct anon_irqchip {
104     irqchip: u32,
105     pin: u32,
106 }
107 
108 #[repr(C)]
109 #[derive(Copy, Clone)]
110 pub struct anon_msi {
111     address: u64,
112     data: u32,
113 }
114 
115 #[repr(C)]
116 pub union anon_route {
117     irqchip: anon_irqchip,
118     msi: anon_msi,
119     reserved: [u8; 16],
120 }
121 
122 #[repr(C)]
123 pub struct crosvm_irq_route {
124     irq_id: u32,
125     kind: u32,
126     route: anon_route,
127 }
128 
129 const CROSVM_MAX_HINT_COUNT: u32 = 1;
130 const CROSVM_MAX_HINT_DETAIL_COUNT: u32 = 32;
131 const CROSVM_HINT_ON_WRITE: u16 = 1;
132 
133 #[repr(C)]
134 pub struct crosvm_hint {
135     hint_version: u32,
136     reserved: u32,
137     address_space: u32,
138     address_flags: u16,
139     details_count: u16,
140     address: u64,
141     details: *const crosvm_hint_detail,
142 }
143 
144 #[repr(C)]
145 pub struct crosvm_hint_detail {
146     match_rax: bool,
147     match_rbx: bool,
148     match_rcx: bool,
149     match_rdx: bool,
150     reserved1: [u8; 4],
151     rax: u64,
152     rbx: u64,
153     rcx: u64,
154     rdx: u64,
155     send_sregs: bool,
156     send_debugregs: bool,
157     reserved2: [u8; 6],
158 }
159 
proto_error_to_int(e: protobuf::Error) -> c_int160 fn proto_error_to_int(e: protobuf::Error) -> c_int {
161     std::io::Error::from(e).raw_os_error().unwrap_or(EINVAL)
162 }
163 
fd_cast<F: FromRawFd>(f: File) -> F164 fn fd_cast<F: FromRawFd>(f: File) -> F {
165     // SAFETY:
166     // Safe because we are transferring unique ownership.
167     unsafe { F::from_raw_fd(f.into_raw_fd()) }
168 }
169 
170 #[derive(Default)]
171 struct IdAllocator(AtomicUsize);
172 
173 impl IdAllocator {
alloc(&self) -> u32174     fn alloc(&self) -> u32 {
175         self.0.fetch_add(1, Ordering::Relaxed) as u32
176     }
177 
free(&self, id: u32)178     fn free(&self, id: u32) {
179         let _ = self.0.compare_exchange(
180             id as usize + 1,
181             id as usize,
182             Ordering::Relaxed,
183             Ordering::Relaxed,
184         );
185     }
186 }
187 
188 #[repr(u8)]
189 #[derive(Debug, Clone, Copy)]
190 pub enum Stat {
191     IoEvent,
192     MemoryGetDirtyLog,
193     IrqEventGetFd,
194     IrqEventGetResampleFd,
195     Connect,
196     DestroyConnection,
197     GetShutdownEvent,
198     CheckExtentsion,
199     EnableVmCapability,
200     EnableVcpuCapability,
201     GetSupportedCpuid,
202     GetEmulatedCpuid,
203     GetHypervCpuid,
204     GetMsrIndexList,
205     NetGetConfig,
206     ReserveRange,
207     ReserveAsyncWriteRange,
208     SetIrq,
209     SetIrqRouting,
210     GetPicState,
211     SetPicState,
212     GetIoapicState,
213     SetIoapicState,
214     GetPitState,
215     SetPitState,
216     GetClock,
217     SetClock,
218     SetIdentityMapAddr,
219     PauseVcpus,
220     Start,
221     GetVcpu,
222     VcpuWait,
223     VcpuResume,
224     VcpuGetRegs,
225     VcpuSetRegs,
226     VcpuGetSregs,
227     VcpuSetSregs,
228     GetFpu,
229     SetFpu,
230     GetDebugRegs,
231     SetDebugRegs,
232     GetXCRegs,
233     SetXCRegs,
234     VcpuGetMsrs,
235     VcpuSetMsrs,
236     VcpuSetCpuid,
237     VcpuGetLapicState,
238     VcpuSetLapicState,
239     VcpuGetMpState,
240     VcpuSetMpState,
241     VcpuGetVcpuEvents,
242     VcpuSetVcpuEvents,
243     NewConnection,
244     SetHypercallHint,
245 
246     Count,
247 }
248 
249 #[cfg(feature = "stats")]
record(a: Stat) -> stats::StatUpdater250 fn record(a: Stat) -> stats::StatUpdater {
251     unsafe { stats::STATS.record(a) }
252 }
253 
254 #[cfg(not(feature = "stats"))]
record(_a: Stat) -> u32255 fn record(_a: Stat) -> u32 {
256     0
257 }
258 
259 #[cfg(feature = "stats")]
printstats()260 fn printstats() {
261     // Unsafe due to racy access - OK for stats
262     if std::env::var(CROSVM_STATS_ENV).is_ok() {
263         unsafe {
264             stats::STATS.print();
265         }
266     }
267 }
268 
269 #[cfg(not(feature = "stats"))]
printstats()270 fn printstats() {}
271 
272 pub struct crosvm {
273     id_allocator: Arc<IdAllocator>,
274     socket: ScmSocket<UnixDatagram>,
275     request_buffer: Vec<u8>,
276     response_buffer: Vec<u8>,
277     vcpus: Arc<[crosvm_vcpu]>,
278 }
279 
280 impl crosvm {
from_connection(socket: UnixDatagram) -> result::Result<crosvm, c_int>281     fn from_connection(socket: UnixDatagram) -> result::Result<crosvm, c_int> {
282         let mut crosvm = crosvm {
283             id_allocator: Default::default(),
284             socket: socket.try_into().map_err(|_| -1)?,
285             request_buffer: Vec::new(),
286             response_buffer: vec![0; MAX_DATAGRAM_SIZE],
287             vcpus: Arc::new([]),
288         };
289         crosvm.load_all_vcpus()?;
290         Ok(crosvm)
291     }
292 
new( id_allocator: Arc<IdAllocator>, socket: UnixDatagram, vcpus: Arc<[crosvm_vcpu]>, ) -> crosvm293     fn new(
294         id_allocator: Arc<IdAllocator>,
295         socket: UnixDatagram,
296         vcpus: Arc<[crosvm_vcpu]>,
297     ) -> crosvm {
298         crosvm {
299             id_allocator,
300             socket: socket.try_into().unwrap(),
301             request_buffer: Vec::new(),
302             response_buffer: vec![0; MAX_DATAGRAM_SIZE],
303             vcpus,
304         }
305     }
306 
get_id_allocator(&self) -> &IdAllocator307     fn get_id_allocator(&self) -> &IdAllocator {
308         &self.id_allocator
309     }
310 
main_transaction( &mut self, request: &MainRequest, fds: &[RawFd], ) -> result::Result<(MainResponse, Vec<File>), c_int>311     fn main_transaction(
312         &mut self,
313         request: &MainRequest,
314         fds: &[RawFd],
315     ) -> result::Result<(MainResponse, Vec<File>), c_int> {
316         self.request_buffer.clear();
317         request
318             .write_to_vec(&mut self.request_buffer)
319             .map_err(proto_error_to_int)?;
320         self.socket
321             .send_with_fds(&self.request_buffer, fds)
322             // raw_os_error is expected to be `Some` because it is constructed via
323             // `std::io::Error::last_os_error()`.
324             .map_err(|e| -e.raw_os_error().unwrap_or(EINVAL))?;
325 
326         let (msg_size, datagram_descriptors) = self
327             .socket
328             .recv_with_fds(
329                 &mut self.response_buffer,
330                 MAX_DATAGRAM_FD,
331             )
332             // raw_os_error is expected to be `Some` because it is constructed via
333             // `std::io::Error::last_os_error()`.
334             .map_err(|e| -e.raw_os_error().unwrap_or(EINVAL))?;
335 
336         let datagram_files = datagram_descriptors.into_iter().map(File::from).collect();
337 
338         let response: MainResponse = Message::parse_from_bytes(&self.response_buffer[..msg_size])
339             .map_err(proto_error_to_int)?;
340         if response.errno != 0 {
341             return Err(response.errno);
342         }
343         Ok((response, datagram_files))
344     }
345 
try_clone(&mut self) -> result::Result<crosvm, c_int>346     fn try_clone(&mut self) -> result::Result<crosvm, c_int> {
347         let mut r = MainRequest::new();
348         r.mut_new_connection();
349         let mut files = self.main_transaction(&r, &[])?.1;
350         match files.pop() {
351             Some(new_socket) => Ok(crosvm::new(
352                 self.id_allocator.clone(),
353                 fd_cast(new_socket),
354                 self.vcpus.clone(),
355             )),
356             None => Err(EPROTO),
357         }
358     }
359 
destroy(&mut self, id: u32) -> result::Result<(), c_int>360     fn destroy(&mut self, id: u32) -> result::Result<(), c_int> {
361         let mut r = MainRequest::new();
362         r.mut_destroy().id = id;
363         self.main_transaction(&r, &[])?;
364         self.get_id_allocator().free(id);
365         printstats();
366         Ok(())
367     }
368 
369     // Only call this at `from_connection` function.
load_all_vcpus(&mut self) -> result::Result<(), c_int>370     fn load_all_vcpus(&mut self) -> result::Result<(), c_int> {
371         let mut r = MainRequest::new();
372         r.mut_get_vcpus();
373         let (_, mut files) = self.main_transaction(&r, &[])?;
374         if files.is_empty() || files.len() % 2 != 0 {
375             return Err(EPROTO);
376         }
377 
378         let mut vcpus = Vec::with_capacity(files.len() / 2);
379         while files.len() > 1 {
380             let write_pipe = files.remove(0);
381             let read_pipe = files.remove(0);
382             vcpus.push(crosvm_vcpu::new(fd_cast(read_pipe), fd_cast(write_pipe)));
383         }
384         self.vcpus = Arc::from(vcpus);
385         Ok(())
386     }
387 
get_shutdown_event(&mut self) -> result::Result<File, c_int>388     fn get_shutdown_event(&mut self) -> result::Result<File, c_int> {
389         let mut r = MainRequest::new();
390         r.mut_get_shutdown_eventfd();
391         let (_, mut files) = self.main_transaction(&r, &[])?;
392         match files.pop() {
393             Some(f) => Ok(f),
394             None => Err(EPROTO),
395         }
396     }
397 
check_extension(&mut self, extension: u32) -> result::Result<bool, c_int>398     fn check_extension(&mut self, extension: u32) -> result::Result<bool, c_int> {
399         let mut r = MainRequest::new();
400         r.mut_check_extension().extension = extension;
401         let (response, _) = self.main_transaction(&r, &[])?;
402         if !response.has_check_extension() {
403             return Err(EPROTO);
404         }
405         Ok(response.check_extension().has_extension)
406     }
407 
get_supported_cpuid( &mut self, cpuid_entries: &mut [kvm_cpuid_entry2], cpuid_count: &mut usize, ) -> result::Result<(), c_int>408     fn get_supported_cpuid(
409         &mut self,
410         cpuid_entries: &mut [kvm_cpuid_entry2],
411         cpuid_count: &mut usize,
412     ) -> result::Result<(), c_int> {
413         *cpuid_count = 0;
414 
415         let mut r = MainRequest::new();
416         r.mut_get_supported_cpuid();
417 
418         let (response, _) = self.main_transaction(&r, &[])?;
419         if !response.has_get_supported_cpuid() {
420             return Err(EPROTO);
421         }
422 
423         let supported_cpuids = response.get_supported_cpuid();
424 
425         *cpuid_count = supported_cpuids.entries.len();
426         if *cpuid_count > cpuid_entries.len() {
427             return Err(E2BIG);
428         }
429 
430         for (proto_entry, kvm_entry) in supported_cpuids
431             .entries
432             .iter()
433             .zip(cpuid_entries.iter_mut())
434         {
435             *kvm_entry = cpuid_proto_to_kvm(proto_entry);
436         }
437 
438         Ok(())
439     }
440 
get_emulated_cpuid( &mut self, cpuid_entries: &mut [kvm_cpuid_entry2], cpuid_count: &mut usize, ) -> result::Result<(), c_int>441     fn get_emulated_cpuid(
442         &mut self,
443         cpuid_entries: &mut [kvm_cpuid_entry2],
444         cpuid_count: &mut usize,
445     ) -> result::Result<(), c_int> {
446         *cpuid_count = 0;
447 
448         let mut r = MainRequest::new();
449         r.mut_get_emulated_cpuid();
450 
451         let (response, _) = self.main_transaction(&r, &[])?;
452         if !response.has_get_emulated_cpuid() {
453             return Err(EPROTO);
454         }
455 
456         let emulated_cpuids = response.get_emulated_cpuid();
457 
458         *cpuid_count = emulated_cpuids.entries.len();
459         if *cpuid_count > cpuid_entries.len() {
460             return Err(E2BIG);
461         }
462 
463         for (proto_entry, kvm_entry) in emulated_cpuids.entries.iter().zip(cpuid_entries.iter_mut())
464         {
465             *kvm_entry = cpuid_proto_to_kvm(proto_entry);
466         }
467 
468         Ok(())
469     }
470 
get_msr_index_list( &mut self, msr_indices: &mut [u32], msr_count: &mut usize, ) -> result::Result<(), c_int>471     fn get_msr_index_list(
472         &mut self,
473         msr_indices: &mut [u32],
474         msr_count: &mut usize,
475     ) -> result::Result<(), c_int> {
476         *msr_count = 0;
477 
478         let mut r = MainRequest::new();
479         r.mut_get_msr_index_list();
480 
481         let (response, _) = self.main_transaction(&r, &[])?;
482         if !response.has_get_msr_index_list() {
483             return Err(EPROTO);
484         }
485 
486         let msr_list = response.get_msr_index_list();
487 
488         *msr_count = msr_list.indices.len();
489         if *msr_count > msr_indices.len() {
490             return Err(E2BIG);
491         }
492 
493         for (proto_entry, kvm_entry) in msr_list.indices.iter().zip(msr_indices.iter_mut()) {
494             *kvm_entry = *proto_entry;
495         }
496 
497         Ok(())
498     }
499 
reserve_range( &mut self, space: u32, start: u64, length: u64, async_write: bool, ) -> result::Result<(), c_int>500     fn reserve_range(
501         &mut self,
502         space: u32,
503         start: u64,
504         length: u64,
505         async_write: bool,
506     ) -> result::Result<(), c_int> {
507         let mut r = MainRequest::new();
508         let reserve = r.mut_reserve_range();
509         reserve.space = AddressSpace::from_i32(space as i32).ok_or(EINVAL)?.into();
510         reserve.start = start;
511         reserve.length = length;
512         reserve.async_write = async_write;
513 
514         self.main_transaction(&r, &[])?;
515         Ok(())
516     }
517 
set_irq(&mut self, irq_id: u32, active: bool) -> result::Result<(), c_int>518     fn set_irq(&mut self, irq_id: u32, active: bool) -> result::Result<(), c_int> {
519         let mut r = MainRequest::new();
520         let set_irq = r.mut_set_irq();
521         set_irq.irq_id = irq_id;
522         set_irq.active = active;
523 
524         self.main_transaction(&r, &[])?;
525         Ok(())
526     }
527 
set_irq_routing(&mut self, routing: &[crosvm_irq_route]) -> result::Result<(), c_int>528     fn set_irq_routing(&mut self, routing: &[crosvm_irq_route]) -> result::Result<(), c_int> {
529         let mut r = MainRequest::new();
530         let set_irq_routing = &mut r.mut_set_irq_routing().routes;
531         for route in routing {
532             let mut entry = main_request::set_irq_routing::Route::new();
533             entry.irq_id = route.irq_id;
534             match route.kind {
535                 CROSVM_IRQ_ROUTE_IRQCHIP => {
536                     let irqchip = entry.mut_irqchip();
537                     // SAFETY:
538                     // Safe because route.kind indicates which union field is valid.
539                     irqchip.irqchip = unsafe { route.route.irqchip }.irqchip;
540                     // SAFETY:
541                     // Safe because route.kind indicates which union field is valid.
542                     irqchip.pin = unsafe { route.route.irqchip }.pin;
543                 }
544                 CROSVM_IRQ_ROUTE_MSI => {
545                     let msi = entry.mut_msi();
546                     // SAFETY:
547                     // Safe because route.kind indicates which union field is valid.
548                     msi.address = unsafe { route.route.msi }.address;
549                     // SAFETY:
550                     // Safe because route.kind indicates which union field is valid.
551                     msi.data = unsafe { route.route.msi }.data;
552                 }
553                 _ => return Err(EINVAL),
554             }
555             set_irq_routing.push(entry);
556         }
557 
558         self.main_transaction(&r, &[])?;
559         Ok(())
560     }
561 
set_hint( &mut self, space: u32, addr: u64, on_write: bool, hints: &[crosvm_hint_detail], ) -> result::Result<(), c_int>562     fn set_hint(
563         &mut self,
564         space: u32,
565         addr: u64,
566         on_write: bool,
567         hints: &[crosvm_hint_detail],
568     ) -> result::Result<(), c_int> {
569         let mut r = MainRequest::new();
570         let req = r.mut_set_call_hint();
571         let set_hints = &mut req.hints;
572         for hint in hints {
573             let mut entry = main_request::set_call_hint::RegHint::new();
574             entry.match_rax = hint.match_rax;
575             entry.match_rbx = hint.match_rbx;
576             entry.match_rcx = hint.match_rcx;
577             entry.match_rdx = hint.match_rdx;
578             entry.rax = hint.rax;
579             entry.rbx = hint.rbx;
580             entry.rcx = hint.rcx;
581             entry.rdx = hint.rdx;
582             entry.send_sregs = hint.send_sregs;
583             entry.send_debugregs = hint.send_debugregs;
584             set_hints.push(entry);
585         }
586         req.space = AddressSpace::from_i32(space as i32).ok_or(EINVAL)?.into();
587         req.address = addr;
588         req.on_write = on_write;
589 
590         self.main_transaction(&r, &[])?;
591         Ok(())
592     }
593 
get_state( &mut self, state_set: main_request::StateSet, out: &mut [u8], ) -> result::Result<(), c_int>594     fn get_state(
595         &mut self,
596         state_set: main_request::StateSet,
597         out: &mut [u8],
598     ) -> result::Result<(), c_int> {
599         let mut r = MainRequest::new();
600         r.mut_get_state().set = state_set.into();
601         let (response, _) = self.main_transaction(&r, &[])?;
602         if !response.has_get_state() {
603             return Err(EPROTO);
604         }
605         let get_state = response.get_state();
606         if get_state.state.len() != out.len() {
607             return Err(EPROTO);
608         }
609         out.copy_from_slice(&get_state.state);
610         Ok(())
611     }
612 
set_state( &mut self, state_set: main_request::StateSet, new_state: &[u8], ) -> result::Result<(), c_int>613     fn set_state(
614         &mut self,
615         state_set: main_request::StateSet,
616         new_state: &[u8],
617     ) -> result::Result<(), c_int> {
618         let mut r = MainRequest::new();
619         let set_state = r.mut_set_state();
620         set_state.set = state_set.into();
621         set_state.state = new_state.to_vec();
622 
623         self.main_transaction(&r, &[])?;
624         Ok(())
625     }
626 
set_identity_map_addr(&mut self, addr: u32) -> result::Result<(), c_int>627     fn set_identity_map_addr(&mut self, addr: u32) -> result::Result<(), c_int> {
628         let mut r = MainRequest::new();
629         r.mut_set_identity_map_addr().address = addr;
630 
631         self.main_transaction(&r, &[])?;
632         Ok(())
633     }
634 
pause_vcpus(&mut self, cpu_mask: u64, user: *mut c_void) -> result::Result<(), c_int>635     fn pause_vcpus(&mut self, cpu_mask: u64, user: *mut c_void) -> result::Result<(), c_int> {
636         let mut r = MainRequest::new();
637         let pause_vcpus = r.mut_pause_vcpus();
638         pause_vcpus.cpu_mask = cpu_mask;
639         pause_vcpus.user = user as u64;
640         self.main_transaction(&r, &[])?;
641         Ok(())
642     }
643 
start(&mut self) -> result::Result<(), c_int>644     fn start(&mut self) -> result::Result<(), c_int> {
645         let mut r = MainRequest::new();
646         r.mut_start();
647         self.main_transaction(&r, &[])?;
648         Ok(())
649     }
650 
get_vcpu(&mut self, cpu_id: u32) -> Result<*mut crosvm_vcpu, c_int>651     fn get_vcpu(&mut self, cpu_id: u32) -> Result<*mut crosvm_vcpu, c_int> {
652         if let Some(vcpu) = self.vcpus.get(cpu_id as usize) {
653             Ok(vcpu as *const crosvm_vcpu as *mut crosvm_vcpu)
654         } else {
655             Err(ENOENT)
656         }
657     }
658 
get_net_config(&mut self) -> result::Result<crosvm_net_config, c_int>659     fn get_net_config(&mut self) -> result::Result<crosvm_net_config, c_int> {
660         let mut r = MainRequest::new();
661         r.mut_get_net_config();
662 
663         let (response, mut files) = self.main_transaction(&r, &[])?;
664         if !response.has_get_net_config() {
665             return Err(EPROTO);
666         }
667         let config = response.get_net_config();
668 
669         match files.pop() {
670             Some(f) => {
671                 let mut net_config = crosvm_net_config {
672                     tap_fd: f.into_raw_fd(),
673                     host_ipv4_address: config.host_ipv4_address,
674                     netmask: config.netmask,
675                     host_mac_address: [0; 6],
676                     _reserved: [0; 2],
677                 };
678 
679                 let mac_addr = &config.host_mac_address;
680                 if mac_addr.len() != net_config.host_mac_address.len() {
681                     return Err(EPROTO);
682                 }
683                 net_config.host_mac_address.copy_from_slice(mac_addr);
684 
685                 Ok(net_config)
686             }
687             None => Err(EPROTO),
688         }
689     }
690 }
691 
692 /// This helper macro implements the C API's constructor/destructor for a given type. Because they
693 /// all follow the same pattern and include lots of boilerplate unsafe code, it makes sense to write
694 /// it once with this helper macro.
695 macro_rules! impl_ctor_dtor {
696     (
697         $t:ident,
698         $ctor:ident ( $( $x:ident: $y:ty ),* ),
699         $dtor:ident,
700     ) => {
701         #[allow(unused_unsafe)]
702         #[no_mangle]
703         pub unsafe extern fn $ctor(self_: *mut crosvm, $($x: $y,)* obj_ptr: *mut *mut $t) -> c_int {
704             let self_ = &mut (*self_);
705             match $t::create(self_, $($x,)*) {
706                 Ok(obj) => {
707                     *obj_ptr = Box::into_raw(Box::new(obj));
708                     0
709                 }
710                 Err(e) => -e,
711             }
712         }
713         #[no_mangle]
714         pub unsafe extern fn $dtor(self_: *mut crosvm, obj_ptr: *mut *mut $t) -> c_int {
715             let self_ = &mut (*self_);
716             let obj = Box::from_raw(*obj_ptr);
717             match self_.destroy(obj.id) {
718                 Ok(_) => {
719                     *obj_ptr = null_mut();
720                     0
721                 }
722                 Err(e) =>  {
723                     Box::into_raw(obj);
724                     -e
725                 }
726             }
727         }
728     }
729 }
730 
731 pub struct crosvm_io_event {
732     id: u32,
733     evt: File,
734 }
735 
736 impl crosvm_io_event {
737     // Clippy: we use ptr::read_unaligned to read from pointers that may be
738     // underaligned. Dereferencing such a pointer is always undefined behavior
739     // in Rust.
740     //
741     // Lint can be unsuppressed once Clippy recognizes this pattern as correct.
742     // https://github.com/rust-lang/rust-clippy/issues/2881
743     #[allow(clippy::cast_ptr_alignment)]
create( crosvm: &mut crosvm, space: u32, addr: u64, length: u32, datamatch: *const u8, ) -> result::Result<crosvm_io_event, c_int>744     unsafe fn create(
745         crosvm: &mut crosvm,
746         space: u32,
747         addr: u64,
748         length: u32,
749         datamatch: *const u8,
750     ) -> result::Result<crosvm_io_event, c_int> {
751         let datamatch = match length {
752             0 => 0,
753             1 => ptr::read_unaligned(datamatch) as u64,
754             2 => ptr::read_unaligned(datamatch as *const u16) as u64,
755             4 => ptr::read_unaligned(datamatch as *const u32) as u64,
756             8 => ptr::read_unaligned(datamatch as *const u64),
757             _ => return Err(EINVAL),
758         };
759         Self::safe_create(crosvm, space, addr, length, datamatch)
760     }
761 
safe_create( crosvm: &mut crosvm, space: u32, addr: u64, length: u32, datamatch: u64, ) -> result::Result<crosvm_io_event, c_int>762     fn safe_create(
763         crosvm: &mut crosvm,
764         space: u32,
765         addr: u64,
766         length: u32,
767         datamatch: u64,
768     ) -> result::Result<crosvm_io_event, c_int> {
769         let id = crosvm.get_id_allocator().alloc();
770 
771         let mut r = MainRequest::new();
772         let create = r.mut_create();
773         create.id = id;
774         let io_event = create.mut_io_event();
775         io_event.space = AddressSpace::from_i32(space as i32).ok_or(EINVAL)?.into();
776         io_event.address = addr;
777         io_event.length = length;
778         io_event.datamatch = datamatch;
779 
780         let ret = match crosvm.main_transaction(&r, &[]) {
781             Ok((_, mut files)) => match files.pop() {
782                 Some(evt) => return Ok(crosvm_io_event { id, evt }),
783                 None => EPROTO,
784             },
785             Err(e) => e,
786         };
787         crosvm.get_id_allocator().free(id);
788         Err(ret)
789     }
790 }
791 
792 impl_ctor_dtor!(
793     crosvm_io_event,
794     crosvm_create_io_event(space: u32, addr: u64, len: u32, datamatch: *const u8),
795     crosvm_destroy_io_event,
796 );
797 
798 #[no_mangle]
crosvm_io_event_fd(this: *mut crosvm_io_event) -> c_int799 pub unsafe extern "C" fn crosvm_io_event_fd(this: *mut crosvm_io_event) -> c_int {
800     let _u = record(Stat::IoEvent);
801     (*this).evt.as_raw_fd()
802 }
803 
804 pub struct crosvm_memory {
805     id: u32,
806     length: u64,
807 }
808 
809 impl crosvm_memory {
create( crosvm: &mut crosvm, fd: c_int, offset: u64, length: u64, start: u64, read_only: bool, dirty_log: bool, ) -> result::Result<crosvm_memory, c_int>810     fn create(
811         crosvm: &mut crosvm,
812         fd: c_int,
813         offset: u64,
814         length: u64,
815         start: u64,
816         read_only: bool,
817         dirty_log: bool,
818     ) -> result::Result<crosvm_memory, c_int> {
819         const PAGE_MASK: u64 = 0x0fff;
820         if offset & PAGE_MASK != 0 || length & PAGE_MASK != 0 {
821             return Err(EINVAL);
822         }
823         let id = crosvm.get_id_allocator().alloc();
824 
825         let mut r = MainRequest::new();
826         let create = r.mut_create();
827         create.id = id;
828         let memory = create.mut_memory();
829         memory.offset = offset;
830         memory.start = start;
831         memory.length = length;
832         memory.read_only = read_only;
833         memory.dirty_log = dirty_log;
834 
835         let ret = match crosvm.main_transaction(&r, &[fd]) {
836             Ok(_) => return Ok(crosvm_memory { id, length }),
837             Err(e) => e,
838         };
839         crosvm.get_id_allocator().free(id);
840         Err(ret)
841     }
842 
get_dirty_log(&mut self, crosvm: &mut crosvm) -> result::Result<Vec<u8>, c_int>843     fn get_dirty_log(&mut self, crosvm: &mut crosvm) -> result::Result<Vec<u8>, c_int> {
844         let mut r = MainRequest::new();
845         r.mut_dirty_log().id = self.id;
846         let (mut response, _) = crosvm.main_transaction(&r, &[])?;
847         if !response.has_dirty_log() {
848             return Err(EPROTO);
849         }
850         Ok(response.take_dirty_log().bitmap)
851     }
852 }
853 
854 impl_ctor_dtor!(
855     crosvm_memory,
856     crosvm_create_memory(
857         fd: c_int,
858         offset: u64,
859         length: u64,
860         start: u64,
861         read_only: bool,
862         dirty_log: bool
863     ),
864     crosvm_destroy_memory,
865 );
866 
867 #[no_mangle]
crosvm_memory_get_dirty_log( crosvm: *mut crosvm, this: *mut crosvm_memory, log: *mut u8, ) -> c_int868 pub unsafe extern "C" fn crosvm_memory_get_dirty_log(
869     crosvm: *mut crosvm,
870     this: *mut crosvm_memory,
871     log: *mut u8,
872 ) -> c_int {
873     let _u = record(Stat::MemoryGetDirtyLog);
874     let crosvm = &mut *crosvm;
875     let this = &mut *this;
876     let log_slice = slice::from_raw_parts_mut(log, dirty_log_bitmap_size(this.length as usize));
877     match this.get_dirty_log(crosvm) {
878         Ok(bitmap) => {
879             if bitmap.len() == log_slice.len() {
880                 log_slice.copy_from_slice(&bitmap);
881                 0
882             } else {
883                 -EPROTO
884             }
885         }
886         Err(e) => -e,
887     }
888 }
889 
890 pub struct crosvm_irq_event {
891     id: u32,
892     trigger_evt: File,
893     resample_evt: File,
894 }
895 
896 impl crosvm_irq_event {
create(crosvm: &mut crosvm, irq_id: u32) -> result::Result<crosvm_irq_event, c_int>897     fn create(crosvm: &mut crosvm, irq_id: u32) -> result::Result<crosvm_irq_event, c_int> {
898         let id = crosvm.get_id_allocator().alloc();
899 
900         let mut r = MainRequest::new();
901         let create = r.mut_create();
902         create.id = id;
903         let irq_event = create.mut_irq_event();
904         irq_event.irq_id = irq_id;
905         irq_event.resample = true;
906 
907         let ret = match crosvm.main_transaction(&r, &[]) {
908             Ok((_, mut files)) => {
909                 if files.len() >= 2 {
910                     let resample_evt = files.pop().unwrap();
911                     let trigger_evt = files.pop().unwrap();
912                     return Ok(crosvm_irq_event {
913                         id,
914                         trigger_evt,
915                         resample_evt,
916                     });
917                 }
918                 EPROTO
919             }
920             Err(e) => e,
921         };
922         crosvm.get_id_allocator().free(id);
923         Err(ret)
924     }
925 }
926 
927 impl_ctor_dtor!(
928     crosvm_irq_event,
929     crosvm_create_irq_event(irq_id: u32),
930     crosvm_destroy_irq_event,
931 );
932 
933 #[no_mangle]
crosvm_irq_event_get_fd(this: *mut crosvm_irq_event) -> c_int934 pub unsafe extern "C" fn crosvm_irq_event_get_fd(this: *mut crosvm_irq_event) -> c_int {
935     let _u = record(Stat::IrqEventGetFd);
936     (*this).trigger_evt.as_raw_fd()
937 }
938 
939 #[no_mangle]
crosvm_irq_event_get_resample_fd(this: *mut crosvm_irq_event) -> c_int940 pub unsafe extern "C" fn crosvm_irq_event_get_resample_fd(this: *mut crosvm_irq_event) -> c_int {
941     let _u = record(Stat::IrqEventGetResampleFd);
942     (*this).resample_evt.as_raw_fd()
943 }
944 
945 #[allow(dead_code)]
946 #[derive(Copy, Clone)]
947 #[repr(C)]
948 struct anon_io_access {
949     address_space: u32,
950     __reserved0: [u8; 4],
951     address: u64,
952     data: *mut u8,
953     length: u32,
954     is_write: u8,
955     no_resume: u8,
956     __reserved1: [u8; 2],
957 }
958 
959 #[derive(Copy, Clone)]
960 #[repr(C)]
961 struct anon_hyperv_call {
962     input: u64,
963     result: *mut u8,
964     params: [u64; 2],
965 }
966 
967 #[derive(Copy, Clone)]
968 #[repr(C)]
969 struct anon_hyperv_synic {
970     msr: u32,
971     reserved: u32,
972     control: u64,
973     evt_page: u64,
974     msg_page: u64,
975 }
976 
977 #[repr(C)]
978 union anon_vcpu_event {
979     io_access: anon_io_access,
980     user: *mut c_void,
981     hyperv_call: anon_hyperv_call,
982     hyperv_synic: anon_hyperv_synic,
983     #[allow(dead_code)]
984     __reserved: [u8; 64],
985 }
986 
987 #[repr(C)]
988 pub struct crosvm_vcpu_event {
989     kind: u32,
990     __reserved: [u8; 4],
991     event: anon_vcpu_event,
992 }
993 
994 // |get| tracks if the |cache| contains a cached value that can service get()
995 // requests.  A set() call will populate |cache| and |set| to true to record
996 // that the next resume() should apply the state.  We've got two choices on
997 // what to do about |get| on a set(): 1) leave it as true, or 2) clear it and
998 // have any call to get() first apply any pending set.  Currently #2 is used
999 // to favor correctness over performance (it gives KVM a chance to
1000 // modify/massage the values input to the set call). A plugin will rarely
1001 // (if ever) issue a get() after a set() on the same vcpu exit, so opting for
1002 // #1 is unlikely to provide a tangible performance gain.
1003 pub struct crosvm_vcpu_reg_cache {
1004     get: bool,
1005     set: bool,
1006     cache: Vec<u8>,
1007 }
1008 
1009 pub struct crosvm_vcpu {
1010     read_pipe: File,
1011     write_pipe: File,
1012     send_init: bool,
1013     request_buffer: Vec<u8>,
1014     response_buffer: Vec<u8>,
1015     response_base: usize,
1016     response_length: usize,
1017     resume_data: Vec<u8>,
1018 
1019     regs: crosvm_vcpu_reg_cache,
1020     sregs: crosvm_vcpu_reg_cache,
1021     debugregs: crosvm_vcpu_reg_cache,
1022 }
1023 
read_varint32(data: &[u8]) -> (u32, usize)1024 fn read_varint32(data: &[u8]) -> (u32, usize) {
1025     let mut value: u32 = 0;
1026     let mut shift: u32 = 0;
1027     for (i, &b) in data.iter().enumerate() {
1028         if b < 0x80 {
1029             return match (b as u32).checked_shl(shift) {
1030                 None => (0, 0),
1031                 Some(b) => (value | b, i + 1),
1032             };
1033         }
1034         match ((b as u32) & 0x7F).checked_shl(shift) {
1035             None => return (0, 0),
1036             Some(b) => value |= b,
1037         }
1038         shift += 7;
1039     }
1040     (0, 0)
1041 }
1042 
1043 impl crosvm_vcpu {
new(read_pipe: File, write_pipe: File) -> crosvm_vcpu1044     fn new(read_pipe: File, write_pipe: File) -> crosvm_vcpu {
1045         crosvm_vcpu {
1046             read_pipe,
1047             write_pipe,
1048             send_init: true,
1049             request_buffer: Vec::new(),
1050             response_buffer: vec![0; MAX_DATAGRAM_SIZE],
1051             response_base: 0,
1052             response_length: 0,
1053             resume_data: Vec::new(),
1054             regs: crosvm_vcpu_reg_cache {
1055                 get: false,
1056                 set: false,
1057                 cache: vec![],
1058             },
1059             sregs: crosvm_vcpu_reg_cache {
1060                 get: false,
1061                 set: false,
1062                 cache: vec![],
1063             },
1064             debugregs: crosvm_vcpu_reg_cache {
1065                 get: false,
1066                 set: false,
1067                 cache: vec![],
1068             },
1069         }
1070     }
vcpu_send(&mut self, request: &VcpuRequest) -> result::Result<(), c_int>1071     fn vcpu_send(&mut self, request: &VcpuRequest) -> result::Result<(), c_int> {
1072         self.request_buffer.clear();
1073         request
1074             .write_to_vec(&mut self.request_buffer)
1075             .map_err(proto_error_to_int)?;
1076         self.write_pipe
1077             .write(self.request_buffer.as_slice())
1078             .map_err(|e| -e.raw_os_error().unwrap_or(EINVAL))?;
1079         Ok(())
1080     }
1081 
vcpu_recv(&mut self) -> result::Result<VcpuResponse, c_int>1082     fn vcpu_recv(&mut self) -> result::Result<VcpuResponse, c_int> {
1083         if self.response_length == 0 {
1084             let msg_size = self
1085                 .read_pipe
1086                 .read(&mut self.response_buffer)
1087                 .map_err(|e| -e.raw_os_error().unwrap_or(EINVAL))?;
1088             self.response_base = 0;
1089             self.response_length = msg_size;
1090         }
1091         if self.response_length == 0 {
1092             return Err(EINVAL);
1093         }
1094         let (value, bytes) = read_varint32(
1095             &self.response_buffer[self.response_base..self.response_base + self.response_length],
1096         );
1097         let total_size: usize = bytes + value as usize;
1098         if bytes == 0 || total_size > self.response_length {
1099             return Err(EINVAL);
1100         }
1101         let response: VcpuResponse = Message::parse_from_bytes(
1102             &self.response_buffer[self.response_base + bytes..self.response_base + total_size],
1103         )
1104         .map_err(proto_error_to_int)?;
1105         self.response_base += total_size;
1106         self.response_length -= total_size;
1107         if response.errno != 0 {
1108             return Err(response.errno);
1109         }
1110         Ok(response)
1111     }
1112 
vcpu_transaction(&mut self, request: &VcpuRequest) -> result::Result<VcpuResponse, c_int>1113     fn vcpu_transaction(&mut self, request: &VcpuRequest) -> result::Result<VcpuResponse, c_int> {
1114         self.vcpu_send(request)?;
1115         let response: VcpuResponse = self.vcpu_recv()?;
1116         Ok(response)
1117     }
1118 
wait(&mut self, event: &mut crosvm_vcpu_event) -> result::Result<(), c_int>1119     fn wait(&mut self, event: &mut crosvm_vcpu_event) -> result::Result<(), c_int> {
1120         if self.send_init {
1121             self.send_init = false;
1122             let mut r = VcpuRequest::new();
1123             r.mut_wait();
1124             self.vcpu_send(&r)?;
1125         }
1126         let mut response: VcpuResponse = self.vcpu_recv()?;
1127         if !response.has_wait() {
1128             return Err(EPROTO);
1129         }
1130         let wait = response.mut_wait();
1131         if wait.has_init() {
1132             event.kind = CROSVM_VCPU_EVENT_KIND_INIT;
1133             self.regs.get = false;
1134             self.sregs.get = false;
1135             self.debugregs.get = false;
1136             Ok(())
1137         } else if wait.has_io() {
1138             let mut io = wait.take_io();
1139             event.kind = CROSVM_VCPU_EVENT_KIND_IO_ACCESS;
1140             event.event.io_access = anon_io_access {
1141                 address_space: io.space.value() as u32,
1142                 __reserved0: Default::default(),
1143                 address: io.address,
1144                 data: io.data.as_mut_ptr(),
1145                 length: io.data.len() as u32,
1146                 is_write: io.is_write as u8,
1147                 no_resume: io.no_resume as u8,
1148                 __reserved1: Default::default(),
1149             };
1150             self.resume_data = io.data;
1151             self.regs.get = !io.regs.is_empty();
1152             if self.regs.get {
1153                 swap(&mut self.regs.cache, &mut io.regs);
1154             }
1155             self.sregs.get = !io.sregs.is_empty();
1156             if self.sregs.get {
1157                 swap(&mut self.sregs.cache, &mut io.sregs);
1158             }
1159             self.debugregs.get = !io.debugregs.is_empty();
1160             if self.debugregs.get {
1161                 swap(&mut self.debugregs.cache, &mut io.debugregs);
1162             }
1163             Ok(())
1164         } else if wait.has_user() {
1165             let user = wait.user();
1166             event.kind = CROSVM_VCPU_EVENT_KIND_PAUSED;
1167             event.event.user = user.user as *mut c_void;
1168             self.regs.get = false;
1169             self.sregs.get = false;
1170             self.debugregs.get = false;
1171             Ok(())
1172         } else if wait.has_hyperv_call() {
1173             let hv = wait.hyperv_call();
1174             event.kind = CROSVM_VCPU_EVENT_KIND_HYPERV_HCALL;
1175             self.resume_data = vec![0; 8];
1176             event.event.hyperv_call = anon_hyperv_call {
1177                 input: hv.input,
1178                 result: self.resume_data.as_mut_ptr(),
1179                 params: [hv.params0, hv.params1],
1180             };
1181             self.regs.get = false;
1182             self.sregs.get = false;
1183             self.debugregs.get = false;
1184             Ok(())
1185         } else if wait.has_hyperv_synic() {
1186             let hv = wait.hyperv_synic();
1187             event.kind = CROSVM_VCPU_EVENT_KIND_HYPERV_SYNIC;
1188             event.event.hyperv_synic = anon_hyperv_synic {
1189                 msr: hv.msr,
1190                 reserved: 0,
1191                 control: hv.control,
1192                 evt_page: hv.evt_page,
1193                 msg_page: hv.msg_page,
1194             };
1195             self.regs.get = false;
1196             self.sregs.get = false;
1197             self.debugregs.get = false;
1198             Ok(())
1199         } else {
1200             Err(EPROTO)
1201         }
1202     }
1203 
resume(&mut self) -> result::Result<(), c_int>1204     fn resume(&mut self) -> result::Result<(), c_int> {
1205         let mut r = VcpuRequest::new();
1206         let resume = r.mut_resume();
1207         swap(&mut resume.data, &mut self.resume_data);
1208 
1209         if self.regs.set {
1210             swap(&mut resume.regs, &mut self.regs.cache);
1211             self.regs.set = false;
1212         }
1213         if self.sregs.set {
1214             swap(&mut resume.sregs, &mut self.sregs.cache);
1215             self.sregs.set = false;
1216         }
1217         if self.debugregs.set {
1218             swap(&mut resume.debugregs, &mut self.debugregs.cache);
1219             self.debugregs.set = false;
1220         }
1221 
1222         self.vcpu_send(&r)?;
1223         Ok(())
1224     }
1225 
get_state( &mut self, state_set: vcpu_request::StateSet, out: &mut [u8], ) -> result::Result<(), c_int>1226     fn get_state(
1227         &mut self,
1228         state_set: vcpu_request::StateSet,
1229         out: &mut [u8],
1230     ) -> result::Result<(), c_int> {
1231         let mut r = VcpuRequest::new();
1232         r.mut_get_state().set = state_set.into();
1233         let response = self.vcpu_transaction(&r)?;
1234         if !response.has_get_state() {
1235             return Err(EPROTO);
1236         }
1237         let get_state = response.get_state();
1238         if get_state.state.len() != out.len() {
1239             return Err(EPROTO);
1240         }
1241         out.copy_from_slice(&get_state.state);
1242         Ok(())
1243     }
1244 
set_state( &mut self, state_set: vcpu_request::StateSet, new_state: &[u8], ) -> result::Result<(), c_int>1245     fn set_state(
1246         &mut self,
1247         state_set: vcpu_request::StateSet,
1248         new_state: &[u8],
1249     ) -> result::Result<(), c_int> {
1250         let mut r = VcpuRequest::new();
1251         let set_state = r.mut_set_state();
1252         set_state.set = state_set.into();
1253         set_state.state = new_state.to_vec();
1254 
1255         self.vcpu_transaction(&r)?;
1256         Ok(())
1257     }
1258 
set_state_from_cache( &mut self, state_set: vcpu_request::StateSet, ) -> result::Result<(), c_int>1259     fn set_state_from_cache(
1260         &mut self,
1261         state_set: vcpu_request::StateSet,
1262     ) -> result::Result<(), c_int> {
1263         let mut r = VcpuRequest::new();
1264         let set_state = r.mut_set_state();
1265         set_state.set = state_set.into();
1266         match state_set {
1267             vcpu_request::StateSet::REGS => {
1268                 swap(&mut set_state.state, &mut self.regs.cache);
1269                 self.regs.set = false;
1270             }
1271             vcpu_request::StateSet::SREGS => {
1272                 swap(&mut set_state.state, &mut self.sregs.cache);
1273                 self.sregs.set = false;
1274             }
1275             vcpu_request::StateSet::DEBUGREGS => {
1276                 swap(&mut set_state.state, &mut self.debugregs.cache);
1277                 self.debugregs.set = false;
1278             }
1279             _ => return Err(EINVAL),
1280         }
1281 
1282         self.vcpu_transaction(&r)?;
1283         Ok(())
1284     }
1285 
get_hyperv_cpuid( &mut self, cpuid_entries: &mut [kvm_cpuid_entry2], cpuid_count: &mut usize, ) -> result::Result<(), c_int>1286     fn get_hyperv_cpuid(
1287         &mut self,
1288         cpuid_entries: &mut [kvm_cpuid_entry2],
1289         cpuid_count: &mut usize,
1290     ) -> result::Result<(), c_int> {
1291         *cpuid_count = 0;
1292 
1293         let mut r = VcpuRequest::new();
1294         r.mut_get_hyperv_cpuid();
1295 
1296         let response = self.vcpu_transaction(&r)?;
1297         if !response.has_get_hyperv_cpuid() {
1298             return Err(EPROTO);
1299         }
1300 
1301         let hyperv_cpuids = response.get_hyperv_cpuid();
1302 
1303         *cpuid_count = hyperv_cpuids.entries.len();
1304         if *cpuid_count > cpuid_entries.len() {
1305             return Err(E2BIG);
1306         }
1307 
1308         for (proto_entry, kvm_entry) in hyperv_cpuids.entries.iter().zip(cpuid_entries.iter_mut()) {
1309             *kvm_entry = cpuid_proto_to_kvm(proto_entry);
1310         }
1311 
1312         Ok(())
1313     }
1314 
get_msrs( &mut self, msr_entries: &mut [kvm_msr_entry], msr_count: &mut usize, ) -> result::Result<(), c_int>1315     fn get_msrs(
1316         &mut self,
1317         msr_entries: &mut [kvm_msr_entry],
1318         msr_count: &mut usize,
1319     ) -> result::Result<(), c_int> {
1320         *msr_count = 0;
1321 
1322         let mut r = VcpuRequest::new();
1323         let entry_indices: &mut Vec<u32> = &mut r.mut_get_msrs().entry_indices;
1324         for entry in msr_entries.iter() {
1325             entry_indices.push(entry.index);
1326         }
1327 
1328         let response = self.vcpu_transaction(&r)?;
1329         if !response.has_get_msrs() {
1330             return Err(EPROTO);
1331         }
1332         let get_msrs = response.get_msrs();
1333         *msr_count = get_msrs.entry_data.len();
1334         if *msr_count > msr_entries.len() {
1335             return Err(E2BIG);
1336         }
1337         for (&msr_data, msr_entry) in get_msrs.entry_data.iter().zip(msr_entries) {
1338             msr_entry.data = msr_data;
1339         }
1340         Ok(())
1341     }
1342 
set_msrs(&mut self, msr_entries: &[kvm_msr_entry]) -> result::Result<(), c_int>1343     fn set_msrs(&mut self, msr_entries: &[kvm_msr_entry]) -> result::Result<(), c_int> {
1344         let mut r = VcpuRequest::new();
1345         let set_msrs_entries = &mut r.mut_set_msrs().entries;
1346         for msr_entry in msr_entries {
1347             let mut entry = vcpu_request::MsrEntry::new();
1348             entry.index = msr_entry.index;
1349             entry.data = msr_entry.data;
1350             set_msrs_entries.push(entry);
1351         }
1352 
1353         self.vcpu_transaction(&r)?;
1354         Ok(())
1355     }
1356 
set_cpuid(&mut self, cpuid_entries: &[kvm_cpuid_entry2]) -> result::Result<(), c_int>1357     fn set_cpuid(&mut self, cpuid_entries: &[kvm_cpuid_entry2]) -> result::Result<(), c_int> {
1358         let mut r = VcpuRequest::new();
1359         let set_cpuid_entries = &mut r.mut_set_cpuid().entries;
1360         for cpuid_entry in cpuid_entries {
1361             set_cpuid_entries.push(cpuid_kvm_to_proto(cpuid_entry));
1362         }
1363 
1364         self.vcpu_transaction(&r)?;
1365         Ok(())
1366     }
1367 
enable_capability(&mut self, capability: u32) -> result::Result<(), c_int>1368     fn enable_capability(&mut self, capability: u32) -> result::Result<(), c_int> {
1369         let mut r = VcpuRequest::new();
1370         r.mut_enable_capability().capability = capability;
1371         self.vcpu_transaction(&r)?;
1372         Ok(())
1373     }
1374 }
1375 
1376 // crosvm API signals success as 0 and errors as negative values
1377 // derived from `errno`.
to_crosvm_rc<T>(r: result::Result<T, c_int>) -> c_int1378 fn to_crosvm_rc<T>(r: result::Result<T, c_int>) -> c_int {
1379     match r {
1380         Ok(_) => 0,
1381         Err(e) => -e,
1382     }
1383 }
1384 
1385 #[no_mangle]
crosvm_connect(out: *mut *mut crosvm) -> c_int1386 pub unsafe extern "C" fn crosvm_connect(out: *mut *mut crosvm) -> c_int {
1387     let _u = record(Stat::Connect);
1388     let socket_name = match env::var(CROSVM_SOCKET_ENV) {
1389         Ok(v) => v,
1390         _ => return -ENOTCONN,
1391     };
1392 
1393     let socket = match socket_name.parse() {
1394         Ok(v) if v < 0 => return -EINVAL,
1395         Ok(v) => v,
1396         _ => return -EINVAL,
1397     };
1398 
1399     let socket = UnixDatagram::from_raw_fd(socket);
1400     let crosvm = match crosvm::from_connection(socket) {
1401         Ok(c) => c,
1402         Err(e) => return -e,
1403     };
1404     *out = Box::into_raw(Box::new(crosvm));
1405     0
1406 }
1407 
1408 #[no_mangle]
crosvm_new_connection(self_: *mut crosvm, out: *mut *mut crosvm) -> c_int1409 pub unsafe extern "C" fn crosvm_new_connection(self_: *mut crosvm, out: *mut *mut crosvm) -> c_int {
1410     let _u = record(Stat::NewConnection);
1411     let self_ = &mut (*self_);
1412     match self_.try_clone() {
1413         Ok(cloned) => {
1414             *out = Box::into_raw(Box::new(cloned));
1415             0
1416         }
1417         Err(e) => -e,
1418     }
1419 }
1420 
1421 #[no_mangle]
crosvm_destroy_connection(self_: *mut *mut crosvm) -> c_int1422 pub unsafe extern "C" fn crosvm_destroy_connection(self_: *mut *mut crosvm) -> c_int {
1423     let _u = record(Stat::DestroyConnection);
1424     drop(Box::from_raw(*self_));
1425     *self_ = null_mut();
1426     0
1427 }
1428 
1429 #[no_mangle]
crosvm_get_shutdown_eventfd(self_: *mut crosvm) -> c_int1430 pub unsafe extern "C" fn crosvm_get_shutdown_eventfd(self_: *mut crosvm) -> c_int {
1431     let _u = record(Stat::GetShutdownEvent);
1432     let self_ = &mut (*self_);
1433     match self_.get_shutdown_event() {
1434         Ok(f) => f.into_raw_fd(),
1435         Err(e) => -e,
1436     }
1437 }
1438 
1439 #[no_mangle]
crosvm_check_extension( self_: *mut crosvm, extension: u32, has_extension: *mut bool, ) -> c_int1440 pub unsafe extern "C" fn crosvm_check_extension(
1441     self_: *mut crosvm,
1442     extension: u32,
1443     has_extension: *mut bool,
1444 ) -> c_int {
1445     let _u = record(Stat::CheckExtentsion);
1446     let self_ = &mut (*self_);
1447     let ret = self_.check_extension(extension);
1448 
1449     if let Ok(supported) = ret {
1450         *has_extension = supported;
1451     }
1452     to_crosvm_rc(ret)
1453 }
1454 
1455 #[no_mangle]
crosvm_enable_capability( _self_: *mut crosvm, _capability: u32, _flags: u32, _args: *const u64, ) -> c_int1456 pub unsafe extern "C" fn crosvm_enable_capability(
1457     _self_: *mut crosvm,
1458     _capability: u32,
1459     _flags: u32,
1460     _args: *const u64,
1461 ) -> c_int {
1462     let _u = record(Stat::EnableVmCapability);
1463     -EINVAL
1464 }
1465 
1466 #[no_mangle]
crosvm_get_supported_cpuid( this: *mut crosvm, entry_count: u32, cpuid_entries: *mut kvm_cpuid_entry2, out_count: *mut u32, ) -> c_int1467 pub unsafe extern "C" fn crosvm_get_supported_cpuid(
1468     this: *mut crosvm,
1469     entry_count: u32,
1470     cpuid_entries: *mut kvm_cpuid_entry2,
1471     out_count: *mut u32,
1472 ) -> c_int {
1473     let _u = record(Stat::GetSupportedCpuid);
1474     let this = &mut *this;
1475     let cpuid_entries = from_raw_parts_mut(cpuid_entries, entry_count as usize);
1476     let mut cpuid_count: usize = 0;
1477     let ret = this.get_supported_cpuid(cpuid_entries, &mut cpuid_count);
1478     *out_count = cpuid_count as u32;
1479     to_crosvm_rc(ret)
1480 }
1481 
1482 #[no_mangle]
crosvm_get_emulated_cpuid( this: *mut crosvm, entry_count: u32, cpuid_entries: *mut kvm_cpuid_entry2, out_count: *mut u32, ) -> c_int1483 pub unsafe extern "C" fn crosvm_get_emulated_cpuid(
1484     this: *mut crosvm,
1485     entry_count: u32,
1486     cpuid_entries: *mut kvm_cpuid_entry2,
1487     out_count: *mut u32,
1488 ) -> c_int {
1489     let _u = record(Stat::GetEmulatedCpuid);
1490     let this = &mut *this;
1491     let cpuid_entries = from_raw_parts_mut(cpuid_entries, entry_count as usize);
1492     let mut cpuid_count: usize = 0;
1493     let ret = this.get_emulated_cpuid(cpuid_entries, &mut cpuid_count);
1494     *out_count = cpuid_count as u32;
1495     to_crosvm_rc(ret)
1496 }
1497 
1498 #[no_mangle]
crosvm_get_msr_index_list( this: *mut crosvm, entry_count: u32, msr_indices: *mut u32, out_count: *mut u32, ) -> c_int1499 pub unsafe extern "C" fn crosvm_get_msr_index_list(
1500     this: *mut crosvm,
1501     entry_count: u32,
1502     msr_indices: *mut u32,
1503     out_count: *mut u32,
1504 ) -> c_int {
1505     let _u = record(Stat::GetMsrIndexList);
1506     let this = &mut *this;
1507     let msr_indices = from_raw_parts_mut(msr_indices, entry_count as usize);
1508     let mut msr_count: usize = 0;
1509     let ret = this.get_msr_index_list(msr_indices, &mut msr_count);
1510     *out_count = msr_count as u32;
1511     to_crosvm_rc(ret)
1512 }
1513 
1514 #[no_mangle]
crosvm_net_get_config( self_: *mut crosvm, config: *mut crosvm_net_config, ) -> c_int1515 pub unsafe extern "C" fn crosvm_net_get_config(
1516     self_: *mut crosvm,
1517     config: *mut crosvm_net_config,
1518 ) -> c_int {
1519     let _u = record(Stat::NetGetConfig);
1520     let self_ = &mut (*self_);
1521     let ret = self_.get_net_config();
1522 
1523     if let Ok(c) = ret {
1524         *config = c;
1525     }
1526 
1527     to_crosvm_rc(ret)
1528 }
1529 
1530 #[no_mangle]
crosvm_reserve_range( self_: *mut crosvm, space: u32, start: u64, length: u64, ) -> c_int1531 pub unsafe extern "C" fn crosvm_reserve_range(
1532     self_: *mut crosvm,
1533     space: u32,
1534     start: u64,
1535     length: u64,
1536 ) -> c_int {
1537     let _u = record(Stat::ReserveRange);
1538     let self_ = &mut (*self_);
1539     let ret = self_.reserve_range(space, start, length, false);
1540     to_crosvm_rc(ret)
1541 }
1542 
1543 #[no_mangle]
crosvm_reserve_async_write_range( self_: *mut crosvm, space: u32, start: u64, length: u64, ) -> c_int1544 pub unsafe extern "C" fn crosvm_reserve_async_write_range(
1545     self_: *mut crosvm,
1546     space: u32,
1547     start: u64,
1548     length: u64,
1549 ) -> c_int {
1550     let _u = record(Stat::ReserveAsyncWriteRange);
1551     let self_ = &mut (*self_);
1552     let ret = self_.reserve_range(space, start, length, true);
1553     to_crosvm_rc(ret)
1554 }
1555 
1556 #[no_mangle]
crosvm_set_irq(self_: *mut crosvm, irq_id: u32, active: bool) -> c_int1557 pub unsafe extern "C" fn crosvm_set_irq(self_: *mut crosvm, irq_id: u32, active: bool) -> c_int {
1558     let _u = record(Stat::SetIrq);
1559     let self_ = &mut (*self_);
1560     let ret = self_.set_irq(irq_id, active);
1561     to_crosvm_rc(ret)
1562 }
1563 
1564 #[no_mangle]
crosvm_set_irq_routing( self_: *mut crosvm, route_count: u32, routes: *const crosvm_irq_route, ) -> c_int1565 pub unsafe extern "C" fn crosvm_set_irq_routing(
1566     self_: *mut crosvm,
1567     route_count: u32,
1568     routes: *const crosvm_irq_route,
1569 ) -> c_int {
1570     let _u = record(Stat::SetIrqRouting);
1571     let self_ = &mut (*self_);
1572     let ret = self_.set_irq_routing(slice::from_raw_parts(routes, route_count as usize));
1573     to_crosvm_rc(ret)
1574 }
1575 
1576 #[no_mangle]
crosvm_set_hypercall_hint( self_: *mut crosvm, hints_count: u32, hints: *const crosvm_hint, ) -> c_int1577 pub unsafe extern "C" fn crosvm_set_hypercall_hint(
1578     self_: *mut crosvm,
1579     hints_count: u32,
1580     hints: *const crosvm_hint,
1581 ) -> c_int {
1582     let _u = record(Stat::SetHypercallHint);
1583     let self_ = &mut (*self_);
1584 
1585     if hints_count < 1 {
1586         let ret = self_.set_hint(0, 0, false, &[]);
1587         return to_crosvm_rc(ret);
1588     }
1589     if hints_count > CROSVM_MAX_HINT_COUNT {
1590         return -EINVAL;
1591     }
1592     let hints = slice::from_raw_parts(hints, hints_count as usize);
1593     let hint = &hints[0];
1594     if hint.hint_version != 0
1595         || hint.reserved != 0
1596         || hint.address == 0
1597         || (hint.address_flags != 0 && hint.address_flags != CROSVM_HINT_ON_WRITE)
1598         || hint.details_count > CROSVM_MAX_HINT_DETAIL_COUNT as u16
1599     {
1600         return -EINVAL;
1601     }
1602     let ret = self_.set_hint(
1603         hint.address_space,
1604         hint.address,
1605         hint.address_flags == CROSVM_HINT_ON_WRITE,
1606         slice::from_raw_parts(hint.details, hint.details_count as usize),
1607     );
1608     to_crosvm_rc(ret)
1609 }
1610 
1611 #[no_mangle]
crosvm_get_pic_state( this: *mut crosvm, primary: bool, state: *mut kvm_pic_state, ) -> c_int1612 pub unsafe extern "C" fn crosvm_get_pic_state(
1613     this: *mut crosvm,
1614     primary: bool,
1615     state: *mut kvm_pic_state,
1616 ) -> c_int {
1617     let _u = record(Stat::GetPicState);
1618     let this = &mut *this;
1619     let state_set = if primary {
1620         main_request::StateSet::PIC0
1621     } else {
1622         main_request::StateSet::PIC1
1623     };
1624     let state = from_raw_parts_mut(state as *mut u8, size_of::<kvm_pic_state>());
1625     let ret = this.get_state(state_set, state);
1626     to_crosvm_rc(ret)
1627 }
1628 
1629 #[no_mangle]
crosvm_set_pic_state( this: *mut crosvm, primary: bool, state: *mut kvm_pic_state, ) -> c_int1630 pub unsafe extern "C" fn crosvm_set_pic_state(
1631     this: *mut crosvm,
1632     primary: bool,
1633     state: *mut kvm_pic_state,
1634 ) -> c_int {
1635     let _u = record(Stat::SetPicState);
1636     let this = &mut *this;
1637     let state_set = if primary {
1638         main_request::StateSet::PIC0
1639     } else {
1640         main_request::StateSet::PIC1
1641     };
1642     let state = from_raw_parts(state as *mut u8, size_of::<kvm_pic_state>());
1643     let ret = this.set_state(state_set, state);
1644     to_crosvm_rc(ret)
1645 }
1646 
1647 #[no_mangle]
crosvm_get_ioapic_state( this: *mut crosvm, state: *mut kvm_ioapic_state, ) -> c_int1648 pub unsafe extern "C" fn crosvm_get_ioapic_state(
1649     this: *mut crosvm,
1650     state: *mut kvm_ioapic_state,
1651 ) -> c_int {
1652     let _u = record(Stat::GetIoapicState);
1653     let this = &mut *this;
1654     let state = from_raw_parts_mut(state as *mut u8, size_of::<kvm_ioapic_state>());
1655     let ret = this.get_state(main_request::StateSet::IOAPIC, state);
1656     to_crosvm_rc(ret)
1657 }
1658 
1659 #[no_mangle]
crosvm_set_ioapic_state( this: *mut crosvm, state: *const kvm_ioapic_state, ) -> c_int1660 pub unsafe extern "C" fn crosvm_set_ioapic_state(
1661     this: *mut crosvm,
1662     state: *const kvm_ioapic_state,
1663 ) -> c_int {
1664     let _u = record(Stat::SetIoapicState);
1665     let this = &mut *this;
1666     let state = from_raw_parts(state as *mut u8, size_of::<kvm_ioapic_state>());
1667     let ret = this.set_state(main_request::StateSet::IOAPIC, state);
1668     to_crosvm_rc(ret)
1669 }
1670 
1671 #[no_mangle]
crosvm_get_pit_state( this: *mut crosvm, state: *mut kvm_pit_state2, ) -> c_int1672 pub unsafe extern "C" fn crosvm_get_pit_state(
1673     this: *mut crosvm,
1674     state: *mut kvm_pit_state2,
1675 ) -> c_int {
1676     let _u = record(Stat::GetPitState);
1677     let this = &mut *this;
1678     let state = from_raw_parts_mut(state as *mut u8, size_of::<kvm_pit_state2>());
1679     let ret = this.get_state(main_request::StateSet::PIT, state);
1680     to_crosvm_rc(ret)
1681 }
1682 
1683 #[no_mangle]
crosvm_set_pit_state( this: *mut crosvm, state: *const kvm_pit_state2, ) -> c_int1684 pub unsafe extern "C" fn crosvm_set_pit_state(
1685     this: *mut crosvm,
1686     state: *const kvm_pit_state2,
1687 ) -> c_int {
1688     let _u = record(Stat::SetPitState);
1689     let this = &mut *this;
1690     let state = from_raw_parts(state as *mut u8, size_of::<kvm_pit_state2>());
1691     let ret = this.set_state(main_request::StateSet::PIT, state);
1692     to_crosvm_rc(ret)
1693 }
1694 
1695 #[no_mangle]
crosvm_get_clock( this: *mut crosvm, clock_data: *mut kvm_clock_data, ) -> c_int1696 pub unsafe extern "C" fn crosvm_get_clock(
1697     this: *mut crosvm,
1698     clock_data: *mut kvm_clock_data,
1699 ) -> c_int {
1700     let _u = record(Stat::GetClock);
1701     let this = &mut *this;
1702     let state = from_raw_parts_mut(clock_data as *mut u8, size_of::<kvm_clock_data>());
1703     let ret = this.get_state(main_request::StateSet::CLOCK, state);
1704     to_crosvm_rc(ret)
1705 }
1706 
1707 #[no_mangle]
crosvm_set_clock( this: *mut crosvm, clock_data: *const kvm_clock_data, ) -> c_int1708 pub unsafe extern "C" fn crosvm_set_clock(
1709     this: *mut crosvm,
1710     clock_data: *const kvm_clock_data,
1711 ) -> c_int {
1712     let _u = record(Stat::SetClock);
1713     let this = &mut *this;
1714     let state = from_raw_parts(clock_data as *mut u8, size_of::<kvm_clock_data>());
1715     let ret = this.set_state(main_request::StateSet::CLOCK, state);
1716     to_crosvm_rc(ret)
1717 }
1718 
1719 #[no_mangle]
crosvm_set_identity_map_addr(self_: *mut crosvm, addr: u32) -> c_int1720 pub unsafe extern "C" fn crosvm_set_identity_map_addr(self_: *mut crosvm, addr: u32) -> c_int {
1721     let _u = record(Stat::SetIdentityMapAddr);
1722     let self_ = &mut (*self_);
1723     let ret = self_.set_identity_map_addr(addr);
1724     to_crosvm_rc(ret)
1725 }
1726 
1727 #[no_mangle]
crosvm_pause_vcpus( self_: *mut crosvm, cpu_mask: u64, user: *mut c_void, ) -> c_int1728 pub unsafe extern "C" fn crosvm_pause_vcpus(
1729     self_: *mut crosvm,
1730     cpu_mask: u64,
1731     user: *mut c_void,
1732 ) -> c_int {
1733     let _u = record(Stat::PauseVcpus);
1734     let self_ = &mut (*self_);
1735     let ret = self_.pause_vcpus(cpu_mask, user);
1736     to_crosvm_rc(ret)
1737 }
1738 
1739 #[no_mangle]
crosvm_start(self_: *mut crosvm) -> c_int1740 pub unsafe extern "C" fn crosvm_start(self_: *mut crosvm) -> c_int {
1741     let _u = record(Stat::Start);
1742     let self_ = &mut (*self_);
1743     let ret = self_.start();
1744     to_crosvm_rc(ret)
1745 }
1746 
1747 #[no_mangle]
crosvm_get_vcpu( self_: *mut crosvm, cpu_id: u32, out: *mut *mut crosvm_vcpu, ) -> c_int1748 pub unsafe extern "C" fn crosvm_get_vcpu(
1749     self_: *mut crosvm,
1750     cpu_id: u32,
1751     out: *mut *mut crosvm_vcpu,
1752 ) -> c_int {
1753     let _u = record(Stat::GetVcpu);
1754     let self_ = &mut (*self_);
1755     let ret = self_.get_vcpu(cpu_id);
1756 
1757     if let Ok(vcpu) = ret {
1758         *out = vcpu;
1759     }
1760     to_crosvm_rc(ret)
1761 }
1762 
1763 #[no_mangle]
crosvm_vcpu_wait( this: *mut crosvm_vcpu, event: *mut crosvm_vcpu_event, ) -> c_int1764 pub unsafe extern "C" fn crosvm_vcpu_wait(
1765     this: *mut crosvm_vcpu,
1766     event: *mut crosvm_vcpu_event,
1767 ) -> c_int {
1768     let _u = record(Stat::VcpuWait);
1769     let this = &mut *this;
1770     let event = &mut *event;
1771     let ret = this.wait(event);
1772     to_crosvm_rc(ret)
1773 }
1774 
1775 #[no_mangle]
crosvm_vcpu_resume(this: *mut crosvm_vcpu) -> c_int1776 pub unsafe extern "C" fn crosvm_vcpu_resume(this: *mut crosvm_vcpu) -> c_int {
1777     let _u = record(Stat::VcpuResume);
1778     let this = &mut *this;
1779     let ret = this.resume();
1780     to_crosvm_rc(ret)
1781 }
1782 
1783 #[no_mangle]
crosvm_vcpu_get_regs( this: *mut crosvm_vcpu, regs: *mut kvm_regs, ) -> c_int1784 pub unsafe extern "C" fn crosvm_vcpu_get_regs(
1785     this: *mut crosvm_vcpu,
1786     regs: *mut kvm_regs,
1787 ) -> c_int {
1788     let _u = record(Stat::VcpuGetRegs);
1789     let this = &mut *this;
1790     if this.regs.set {
1791         if let Err(e) = this.set_state_from_cache(vcpu_request::StateSet::REGS) {
1792             return -e;
1793         }
1794     }
1795     let regs = from_raw_parts_mut(regs as *mut u8, size_of::<kvm_regs>());
1796     if this.regs.get {
1797         regs.copy_from_slice(&this.regs.cache);
1798         0
1799     } else {
1800         let ret = this.get_state(vcpu_request::StateSet::REGS, regs);
1801         to_crosvm_rc(ret)
1802     }
1803 }
1804 
1805 #[no_mangle]
crosvm_vcpu_set_regs( this: *mut crosvm_vcpu, regs: *const kvm_regs, ) -> c_int1806 pub unsafe extern "C" fn crosvm_vcpu_set_regs(
1807     this: *mut crosvm_vcpu,
1808     regs: *const kvm_regs,
1809 ) -> c_int {
1810     let _u = record(Stat::VcpuSetRegs);
1811     let this = &mut *this;
1812     this.regs.get = false;
1813     let regs = from_raw_parts(regs as *mut u8, size_of::<kvm_regs>());
1814     this.regs.set = true;
1815     this.regs.cache = regs.to_vec();
1816     0
1817 }
1818 
1819 #[no_mangle]
crosvm_vcpu_get_sregs( this: *mut crosvm_vcpu, sregs: *mut kvm_sregs, ) -> c_int1820 pub unsafe extern "C" fn crosvm_vcpu_get_sregs(
1821     this: *mut crosvm_vcpu,
1822     sregs: *mut kvm_sregs,
1823 ) -> c_int {
1824     let _u = record(Stat::VcpuGetSregs);
1825     let this = &mut *this;
1826     if this.sregs.set {
1827         if let Err(e) = this.set_state_from_cache(vcpu_request::StateSet::SREGS) {
1828             return -e;
1829         }
1830     }
1831     let sregs = from_raw_parts_mut(sregs as *mut u8, size_of::<kvm_sregs>());
1832     if this.sregs.get {
1833         sregs.copy_from_slice(&this.sregs.cache);
1834         0
1835     } else {
1836         let ret = this.get_state(vcpu_request::StateSet::SREGS, sregs);
1837         to_crosvm_rc(ret)
1838     }
1839 }
1840 
1841 #[no_mangle]
crosvm_vcpu_set_sregs( this: *mut crosvm_vcpu, sregs: *const kvm_sregs, ) -> c_int1842 pub unsafe extern "C" fn crosvm_vcpu_set_sregs(
1843     this: *mut crosvm_vcpu,
1844     sregs: *const kvm_sregs,
1845 ) -> c_int {
1846     let _u = record(Stat::VcpuSetSregs);
1847     let this = &mut *this;
1848     this.sregs.get = false;
1849     let sregs = from_raw_parts(sregs as *mut u8, size_of::<kvm_sregs>());
1850     this.sregs.set = true;
1851     this.sregs.cache = sregs.to_vec();
1852     0
1853 }
1854 
1855 #[no_mangle]
crosvm_vcpu_get_fpu(this: *mut crosvm_vcpu, fpu: *mut kvm_fpu) -> c_int1856 pub unsafe extern "C" fn crosvm_vcpu_get_fpu(this: *mut crosvm_vcpu, fpu: *mut kvm_fpu) -> c_int {
1857     let _u = record(Stat::GetFpu);
1858     let this = &mut *this;
1859     let fpu = from_raw_parts_mut(fpu as *mut u8, size_of::<kvm_fpu>());
1860     let ret = this.get_state(vcpu_request::StateSet::FPU, fpu);
1861     to_crosvm_rc(ret)
1862 }
1863 
1864 #[no_mangle]
crosvm_vcpu_set_fpu(this: *mut crosvm_vcpu, fpu: *const kvm_fpu) -> c_int1865 pub unsafe extern "C" fn crosvm_vcpu_set_fpu(this: *mut crosvm_vcpu, fpu: *const kvm_fpu) -> c_int {
1866     let _u = record(Stat::SetFpu);
1867     let this = &mut *this;
1868     let fpu = from_raw_parts(fpu as *mut u8, size_of::<kvm_fpu>());
1869     let ret = this.set_state(vcpu_request::StateSet::FPU, fpu);
1870     to_crosvm_rc(ret)
1871 }
1872 
1873 #[no_mangle]
crosvm_vcpu_get_debugregs( this: *mut crosvm_vcpu, dregs: *mut kvm_debugregs, ) -> c_int1874 pub unsafe extern "C" fn crosvm_vcpu_get_debugregs(
1875     this: *mut crosvm_vcpu,
1876     dregs: *mut kvm_debugregs,
1877 ) -> c_int {
1878     let _u = record(Stat::GetDebugRegs);
1879     let this = &mut *this;
1880     if this.debugregs.set {
1881         if let Err(e) = this.set_state_from_cache(vcpu_request::StateSet::DEBUGREGS) {
1882             return -e;
1883         }
1884     }
1885     let dregs = from_raw_parts_mut(dregs as *mut u8, size_of::<kvm_debugregs>());
1886     if this.debugregs.get {
1887         dregs.copy_from_slice(&this.debugregs.cache);
1888         0
1889     } else {
1890         let ret = this.get_state(vcpu_request::StateSet::DEBUGREGS, dregs);
1891         to_crosvm_rc(ret)
1892     }
1893 }
1894 
1895 #[no_mangle]
crosvm_vcpu_set_debugregs( this: *mut crosvm_vcpu, dregs: *const kvm_debugregs, ) -> c_int1896 pub unsafe extern "C" fn crosvm_vcpu_set_debugregs(
1897     this: *mut crosvm_vcpu,
1898     dregs: *const kvm_debugregs,
1899 ) -> c_int {
1900     let _u = record(Stat::SetDebugRegs);
1901     let this = &mut *this;
1902     this.debugregs.get = false;
1903     let dregs = from_raw_parts(dregs as *mut u8, size_of::<kvm_debugregs>());
1904     this.debugregs.set = true;
1905     this.debugregs.cache = dregs.to_vec();
1906     0
1907 }
1908 
1909 #[no_mangle]
crosvm_vcpu_get_xcrs( this: *mut crosvm_vcpu, xcrs: *mut kvm_xcrs, ) -> c_int1910 pub unsafe extern "C" fn crosvm_vcpu_get_xcrs(
1911     this: *mut crosvm_vcpu,
1912     xcrs: *mut kvm_xcrs,
1913 ) -> c_int {
1914     let _u = record(Stat::GetXCRegs);
1915     let this = &mut *this;
1916     let xcrs = from_raw_parts_mut(xcrs as *mut u8, size_of::<kvm_xcrs>());
1917     let ret = this.get_state(vcpu_request::StateSet::XCREGS, xcrs);
1918     to_crosvm_rc(ret)
1919 }
1920 
1921 #[no_mangle]
crosvm_vcpu_set_xcrs( this: *mut crosvm_vcpu, xcrs: *const kvm_xcrs, ) -> c_int1922 pub unsafe extern "C" fn crosvm_vcpu_set_xcrs(
1923     this: *mut crosvm_vcpu,
1924     xcrs: *const kvm_xcrs,
1925 ) -> c_int {
1926     let _u = record(Stat::SetXCRegs);
1927     let this = &mut *this;
1928     let xcrs = from_raw_parts(xcrs as *mut u8, size_of::<kvm_xcrs>());
1929     let ret = this.set_state(vcpu_request::StateSet::XCREGS, xcrs);
1930     to_crosvm_rc(ret)
1931 }
1932 
1933 #[no_mangle]
crosvm_get_hyperv_cpuid( this: *mut crosvm_vcpu, entry_count: u32, cpuid_entries: *mut kvm_cpuid_entry2, out_count: *mut u32, ) -> c_int1934 pub unsafe extern "C" fn crosvm_get_hyperv_cpuid(
1935     this: *mut crosvm_vcpu,
1936     entry_count: u32,
1937     cpuid_entries: *mut kvm_cpuid_entry2,
1938     out_count: *mut u32,
1939 ) -> c_int {
1940     let _u = record(Stat::GetHypervCpuid);
1941     let this = &mut *this;
1942     let cpuid_entries = from_raw_parts_mut(cpuid_entries, entry_count as usize);
1943     let mut cpuid_count: usize = 0;
1944     let ret = this.get_hyperv_cpuid(cpuid_entries, &mut cpuid_count);
1945     *out_count = cpuid_count as u32;
1946     to_crosvm_rc(ret)
1947 }
1948 
1949 #[no_mangle]
crosvm_vcpu_get_msrs( this: *mut crosvm_vcpu, msr_count: u32, msr_entries: *mut kvm_msr_entry, out_count: *mut u32, ) -> c_int1950 pub unsafe extern "C" fn crosvm_vcpu_get_msrs(
1951     this: *mut crosvm_vcpu,
1952     msr_count: u32,
1953     msr_entries: *mut kvm_msr_entry,
1954     out_count: *mut u32,
1955 ) -> c_int {
1956     let _u = record(Stat::VcpuGetMsrs);
1957     let this = &mut *this;
1958     let msr_entries = from_raw_parts_mut(msr_entries, msr_count as usize);
1959     let mut count: usize = 0;
1960     let ret = this.get_msrs(msr_entries, &mut count);
1961     *out_count = count as u32;
1962     to_crosvm_rc(ret)
1963 }
1964 
1965 #[no_mangle]
crosvm_vcpu_set_msrs( this: *mut crosvm_vcpu, msr_count: u32, msr_entries: *const kvm_msr_entry, ) -> c_int1966 pub unsafe extern "C" fn crosvm_vcpu_set_msrs(
1967     this: *mut crosvm_vcpu,
1968     msr_count: u32,
1969     msr_entries: *const kvm_msr_entry,
1970 ) -> c_int {
1971     let _u = record(Stat::VcpuSetMsrs);
1972     let this = &mut *this;
1973     let msr_entries = from_raw_parts(msr_entries, msr_count as usize);
1974     let ret = this.set_msrs(msr_entries);
1975     to_crosvm_rc(ret)
1976 }
1977 
1978 #[no_mangle]
crosvm_vcpu_set_cpuid( this: *mut crosvm_vcpu, cpuid_count: u32, cpuid_entries: *const kvm_cpuid_entry2, ) -> c_int1979 pub unsafe extern "C" fn crosvm_vcpu_set_cpuid(
1980     this: *mut crosvm_vcpu,
1981     cpuid_count: u32,
1982     cpuid_entries: *const kvm_cpuid_entry2,
1983 ) -> c_int {
1984     let _u = record(Stat::VcpuSetCpuid);
1985     let this = &mut *this;
1986     let cpuid_entries = from_raw_parts(cpuid_entries, cpuid_count as usize);
1987     let ret = this.set_cpuid(cpuid_entries);
1988     to_crosvm_rc(ret)
1989 }
1990 
1991 #[no_mangle]
crosvm_vcpu_enable_capability( this: *mut crosvm_vcpu, capability: u32, flags: u32, args: *const u64, ) -> c_int1992 pub unsafe extern "C" fn crosvm_vcpu_enable_capability(
1993     this: *mut crosvm_vcpu,
1994     capability: u32,
1995     flags: u32,
1996     args: *const u64,
1997 ) -> c_int {
1998     let _u = record(Stat::EnableVcpuCapability);
1999     let this = &mut *this;
2000     let args = slice::from_raw_parts(args, 4);
2001 
2002     if flags != 0 || args.iter().any(|v| *v != 0) {
2003         return -EINVAL;
2004     }
2005 
2006     let ret = this.enable_capability(capability);
2007     to_crosvm_rc(ret)
2008 }
2009 
2010 #[no_mangle]
crosvm_vcpu_get_lapic_state( this: *mut crosvm_vcpu, state: *mut kvm_lapic_state, ) -> c_int2011 pub unsafe extern "C" fn crosvm_vcpu_get_lapic_state(
2012     this: *mut crosvm_vcpu,
2013     state: *mut kvm_lapic_state,
2014 ) -> c_int {
2015     let _u = record(Stat::VcpuGetLapicState);
2016     let this = &mut *this;
2017     let state = from_raw_parts_mut(state as *mut u8, size_of::<kvm_lapic_state>());
2018     let ret = this.get_state(vcpu_request::StateSet::LAPIC, state);
2019     to_crosvm_rc(ret)
2020 }
2021 
2022 #[no_mangle]
crosvm_vcpu_set_lapic_state( this: *mut crosvm_vcpu, state: *const kvm_lapic_state, ) -> c_int2023 pub unsafe extern "C" fn crosvm_vcpu_set_lapic_state(
2024     this: *mut crosvm_vcpu,
2025     state: *const kvm_lapic_state,
2026 ) -> c_int {
2027     let _u = record(Stat::VcpuSetLapicState);
2028     let this = &mut *this;
2029     let state = from_raw_parts(state as *mut u8, size_of::<kvm_lapic_state>());
2030     let ret = this.set_state(vcpu_request::StateSet::LAPIC, state);
2031     to_crosvm_rc(ret)
2032 }
2033 
2034 #[no_mangle]
crosvm_vcpu_get_mp_state( this: *mut crosvm_vcpu, state: *mut kvm_mp_state, ) -> c_int2035 pub unsafe extern "C" fn crosvm_vcpu_get_mp_state(
2036     this: *mut crosvm_vcpu,
2037     state: *mut kvm_mp_state,
2038 ) -> c_int {
2039     let _u = record(Stat::VcpuGetMpState);
2040     let this = &mut *this;
2041     let state = from_raw_parts_mut(state as *mut u8, size_of::<kvm_mp_state>());
2042     let ret = this.get_state(vcpu_request::StateSet::MP, state);
2043     to_crosvm_rc(ret)
2044 }
2045 
2046 #[no_mangle]
crosvm_vcpu_set_mp_state( this: *mut crosvm_vcpu, state: *const kvm_mp_state, ) -> c_int2047 pub unsafe extern "C" fn crosvm_vcpu_set_mp_state(
2048     this: *mut crosvm_vcpu,
2049     state: *const kvm_mp_state,
2050 ) -> c_int {
2051     let _u = record(Stat::VcpuSetMpState);
2052     let this = &mut *this;
2053     let state = from_raw_parts(state as *mut u8, size_of::<kvm_mp_state>());
2054     let ret = this.set_state(vcpu_request::StateSet::MP, state);
2055     to_crosvm_rc(ret)
2056 }
2057 
2058 #[no_mangle]
crosvm_vcpu_get_vcpu_events( this: *mut crosvm_vcpu, events: *mut kvm_vcpu_events, ) -> c_int2059 pub unsafe extern "C" fn crosvm_vcpu_get_vcpu_events(
2060     this: *mut crosvm_vcpu,
2061     events: *mut kvm_vcpu_events,
2062 ) -> c_int {
2063     let _u = record(Stat::VcpuGetVcpuEvents);
2064     let this = &mut *this;
2065     let events = from_raw_parts_mut(events as *mut u8, size_of::<kvm_vcpu_events>());
2066     let ret = this.get_state(vcpu_request::StateSet::EVENTS, events);
2067     to_crosvm_rc(ret)
2068 }
2069 
2070 #[no_mangle]
crosvm_vcpu_set_vcpu_events( this: *mut crosvm_vcpu, events: *const kvm_vcpu_events, ) -> c_int2071 pub unsafe extern "C" fn crosvm_vcpu_set_vcpu_events(
2072     this: *mut crosvm_vcpu,
2073     events: *const kvm_vcpu_events,
2074 ) -> c_int {
2075     let _u = record(Stat::VcpuSetVcpuEvents);
2076     let this = &mut *this;
2077     let events = from_raw_parts(events as *mut u8, size_of::<kvm_vcpu_events>());
2078     let ret = this.set_state(vcpu_request::StateSet::EVENTS, events);
2079     to_crosvm_rc(ret)
2080 }
2081