1 // Copyright 2017 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #![allow(non_camel_case_types)]
6
7 //! This module implements the dynamically loaded client library API used by a crosvm plugin,
8 //! defined in `crosvm.h`. It implements the client half of the plugin protocol, which is defined in
9 //! the `protos::plugin` module.
10 //!
11 //! To implement the `crosvm.h` C API, each function and struct definition is repeated here, with
12 //! concrete definitions for each struct. Most functions are thin shims to the underlying object
13 //! oriented Rust implementation method. Most methods require a request over the crosvm connection,
14 //! which is done by creating a `MainRequest` or `VcpuRequest` protobuf and sending it over the
15 //! connection's socket. Then, that socket is read for a `MainResponse` or `VcpuResponse`, which is
16 //! translated to the appropriate return type for the C API.
17
18 use std::env;
19 use std::fs::File;
20 use std::io::{Read, Write};
21 use std::mem::{size_of, swap};
22 use std::os::raw::{c_int, c_void};
23 use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
24 use std::os::unix::net::UnixDatagram;
25 use std::ptr::{self, null_mut};
26 use std::result;
27 use std::slice;
28 use std::slice::{from_raw_parts, from_raw_parts_mut};
29 use std::sync::atomic::{AtomicUsize, Ordering};
30 use std::sync::Arc;
31 use std::time::Instant;
32
33 use libc::{E2BIG, EINVAL, ENOENT, ENOTCONN, EPROTO};
34
35 use protobuf::{parse_from_bytes, Message, ProtobufEnum, RepeatedField};
36
37 use sys_util::ScmSocket;
38
39 use kvm::dirty_log_bitmap_size;
40
41 use kvm_sys::{
42 kvm_clock_data, kvm_cpuid_entry2, kvm_debugregs, kvm_fpu, kvm_ioapic_state, kvm_lapic_state,
43 kvm_mp_state, kvm_msr_entry, kvm_pic_state, kvm_pit_state2, kvm_regs, kvm_sregs,
44 kvm_vcpu_events, kvm_xcrs,
45 };
46
47 use protos::plugin::*;
48
49 // Needs to be large enough to receive all the VCPU sockets.
50 const MAX_DATAGRAM_FD: usize = 32;
51 // Needs to be large enough for a sizable dirty log.
52 const MAX_DATAGRAM_SIZE: usize = 0x40000;
53
54 const CROSVM_IRQ_ROUTE_IRQCHIP: u32 = 0;
55 const CROSVM_IRQ_ROUTE_MSI: u32 = 1;
56
57 const CROSVM_VCPU_EVENT_KIND_INIT: u32 = 0;
58 const CROSVM_VCPU_EVENT_KIND_IO_ACCESS: u32 = 1;
59 const CROSVM_VCPU_EVENT_KIND_PAUSED: u32 = 2;
60
61 #[repr(C)]
62 #[derive(Copy, Clone)]
63 pub struct crosvm_net_config {
64 tap_fd: c_int,
65 host_ipv4_address: u32,
66 netmask: u32,
67 host_mac_address: [u8; 6],
68 _reserved: [u8; 2],
69 }
70
71 #[repr(C)]
72 #[derive(Copy, Clone)]
73 pub struct anon_irqchip {
74 irqchip: u32,
75 pin: u32,
76 }
77
78 #[repr(C)]
79 #[derive(Copy, Clone)]
80 pub struct anon_msi {
81 address: u64,
82 data: u32,
83 }
84
85 #[repr(C)]
86 pub union anon_route {
87 irqchip: anon_irqchip,
88 msi: anon_msi,
89 reserved: [u8; 16],
90 }
91
92 #[repr(C)]
93 pub struct crosvm_irq_route {
94 irq_id: u32,
95 kind: u32,
96 route: anon_route,
97 }
98
proto_error_to_int(e: protobuf::ProtobufError) -> c_int99 fn proto_error_to_int(e: protobuf::ProtobufError) -> c_int {
100 match e {
101 protobuf::ProtobufError::IoError(e) => e.raw_os_error().unwrap_or(EINVAL),
102 _ => EINVAL,
103 }
104 }
105
fd_cast<F: FromRawFd>(f: File) -> F106 fn fd_cast<F: FromRawFd>(f: File) -> F {
107 // Safe because we are transferring unique ownership.
108 unsafe { F::from_raw_fd(f.into_raw_fd()) }
109 }
110
111 #[derive(Default)]
112 struct IdAllocator(AtomicUsize);
113
114 impl IdAllocator {
alloc(&self) -> u32115 fn alloc(&self) -> u32 {
116 self.0.fetch_add(1, Ordering::Relaxed) as u32
117 }
118
free(&self, id: u32)119 fn free(&self, id: u32) {
120 self.0
121 .compare_and_swap(id as usize + 1, id as usize, Ordering::Relaxed);
122 }
123 }
124
125 #[repr(u8)]
126 #[derive(Debug, Clone, Copy)]
127 enum Stat {
128 IoEventFd,
129 MemoryGetDirtyLog,
130 IrqEventGetFd,
131 IrqEventGetResampleFd,
132 Connect,
133 DestroyConnection,
134 GetShutdownEventFd,
135 CheckExtentsion,
136 GetSupportedCpuid,
137 GetEmulatedCpuid,
138 GetMsrIndexList,
139 NetGetConfig,
140 ReserveRange,
141 SetIrq,
142 SetIrqRouting,
143 GetPicState,
144 SetPicState,
145 GetIoapicState,
146 SetIoapicState,
147 GetPitState,
148 SetPitState,
149 GetClock,
150 SetClock,
151 SetIdentityMapAddr,
152 PauseVcpus,
153 Start,
154 GetVcpu,
155 VcpuWait,
156 VcpuResume,
157 VcpuGetRegs,
158 VcpuSetRegs,
159 VcpuGetSregs,
160 VcpuSetSregs,
161 GetFpu,
162 SetFpu,
163 GetDebugRegs,
164 SetDebugRegs,
165 GetXCRegs,
166 SetXCRegs,
167 VcpuGetMsrs,
168 VcpuSetMsrs,
169 VcpuSetCpuid,
170 VcpuGetLapicState,
171 VcpuSetLapicState,
172 VcpuGetMpState,
173 VcpuSetMpState,
174 VcpuGetVcpuEvents,
175 VcpuSetVcpuEvents,
176 NewConnection,
177
178 Count,
179 }
180
181 #[derive(Clone, Copy)]
182 struct StatEntry {
183 count: u64,
184 total: u64,
185 max: u64,
186 }
187
188 struct StatUpdater {
189 idx: usize,
190 start: Instant,
191 }
192
193 struct GlobalStats {
194 entries: [StatEntry; Stat::Count as usize],
195 }
196
197 static mut STATS: GlobalStats = GlobalStats {
198 entries: [StatEntry {
199 count: 0,
200 total: 0,
201 max: 0,
202 }; Stat::Count as usize],
203 };
204
205 impl GlobalStats {
206 // Record latency from this call until the end of block/function
207 // Example:
208 // pub fn foo() {
209 // let _u = STATS.record(Stat::Foo);
210 // // ... some operation ...
211 // }
212 // The added STATS.record will record latency of "some operation" and will
213 // update max and average latencies for it under Stats::Foo. Subsequent
214 // call to STATS.print() will print out max and average latencies for all
215 // operations that were performed.
record(&mut self, idx: Stat) -> StatUpdater216 fn record(&mut self, idx: Stat) -> StatUpdater {
217 StatUpdater {
218 idx: idx as usize,
219 start: Instant::now(),
220 }
221 }
222
print(&self)223 fn print(&self) {
224 for idx in 0..Stat::Count as usize {
225 let e = &self.entries[idx as usize];
226 let stat = unsafe { std::mem::transmute::<u8, Stat>(idx as u8) };
227 if e.count > 0 {
228 println!(
229 "Stat::{:?}: avg {}ns max {}ns",
230 stat,
231 e.total / e.count,
232 e.max
233 );
234 }
235 }
236 }
237
update(&mut self, idx: usize, elapsed_nanos: u64)238 fn update(&mut self, idx: usize, elapsed_nanos: u64) {
239 let e = &mut self.entries[idx as usize];
240 e.total += elapsed_nanos;
241 if e.max < elapsed_nanos {
242 e.max = elapsed_nanos;
243 }
244 e.count += 1;
245 }
246 }
247
248 impl Drop for StatUpdater {
drop(&mut self)249 fn drop(&mut self) {
250 let elapsed = self.start.elapsed();
251 let elapsed_nanos = elapsed.as_secs() * 1000000000 + elapsed.subsec_nanos() as u64;
252 // Unsafe due to racy access - OK for stats
253 unsafe {
254 STATS.update(self.idx, elapsed_nanos);
255 }
256 }
257 }
258
259 pub struct crosvm {
260 id_allocator: Arc<IdAllocator>,
261 socket: UnixDatagram,
262 request_buffer: Vec<u8>,
263 response_buffer: Vec<u8>,
264 vcpus: Arc<Vec<crosvm_vcpu>>,
265 }
266
267 impl crosvm {
from_connection(socket: UnixDatagram) -> result::Result<crosvm, c_int>268 fn from_connection(socket: UnixDatagram) -> result::Result<crosvm, c_int> {
269 let mut crosvm = crosvm {
270 id_allocator: Default::default(),
271 socket,
272 request_buffer: Vec::new(),
273 response_buffer: vec![0; MAX_DATAGRAM_SIZE],
274 vcpus: Default::default(),
275 };
276 crosvm.load_all_vcpus()?;
277 Ok(crosvm)
278 }
279
new( id_allocator: Arc<IdAllocator>, socket: UnixDatagram, vcpus: Arc<Vec<crosvm_vcpu>>, ) -> crosvm280 fn new(
281 id_allocator: Arc<IdAllocator>,
282 socket: UnixDatagram,
283 vcpus: Arc<Vec<crosvm_vcpu>>,
284 ) -> crosvm {
285 crosvm {
286 id_allocator,
287 socket,
288 request_buffer: Vec::new(),
289 response_buffer: vec![0; MAX_DATAGRAM_SIZE],
290 vcpus,
291 }
292 }
293
get_id_allocator(&self) -> &IdAllocator294 fn get_id_allocator(&self) -> &IdAllocator {
295 &*self.id_allocator
296 }
297
main_transaction( &mut self, request: &MainRequest, fds: &[RawFd], ) -> result::Result<(MainResponse, Vec<File>), c_int>298 fn main_transaction(
299 &mut self,
300 request: &MainRequest,
301 fds: &[RawFd],
302 ) -> result::Result<(MainResponse, Vec<File>), c_int> {
303 self.request_buffer.clear();
304 request
305 .write_to_vec(&mut self.request_buffer)
306 .map_err(proto_error_to_int)?;
307 self.socket
308 .send_with_fds(self.request_buffer.as_slice(), fds)
309 .map_err(|e| -e.errno())?;
310
311 let mut datagram_fds = [0; MAX_DATAGRAM_FD];
312 let (msg_size, fd_count) = self
313 .socket
314 .recv_with_fds(&mut self.response_buffer, &mut datagram_fds)
315 .map_err(|e| -e.errno())?;
316 // Safe because the first fd_count fds from recv_with_fds are owned by us and valid.
317 let datagram_files = datagram_fds[..fd_count]
318 .iter()
319 .map(|&fd| unsafe { File::from_raw_fd(fd) })
320 .collect();
321
322 let response: MainResponse =
323 parse_from_bytes(&self.response_buffer[..msg_size]).map_err(proto_error_to_int)?;
324 if response.errno != 0 {
325 return Err(response.errno);
326 }
327 Ok((response, datagram_files))
328 }
329
try_clone(&mut self) -> result::Result<crosvm, c_int>330 fn try_clone(&mut self) -> result::Result<crosvm, c_int> {
331 let mut r = MainRequest::new();
332 r.mut_new_connection();
333 let mut files = self.main_transaction(&r, &[])?.1;
334 match files.pop() {
335 Some(new_socket) => Ok(crosvm::new(
336 self.id_allocator.clone(),
337 fd_cast(new_socket),
338 self.vcpus.clone(),
339 )),
340 None => Err(EPROTO),
341 }
342 }
343
destroy(&mut self, id: u32) -> result::Result<(), c_int>344 fn destroy(&mut self, id: u32) -> result::Result<(), c_int> {
345 let mut r = MainRequest::new();
346 r.mut_destroy().id = id;
347 self.main_transaction(&r, &[])?;
348 self.get_id_allocator().free(id);
349 // Unsafe due to racy access - OK for stats
350 if std::env::var("CROSVM_STATS").is_ok() {
351 unsafe {
352 STATS.print();
353 }
354 }
355 Ok(())
356 }
357
358 // Only call this at `from_connection` function.
load_all_vcpus(&mut self) -> result::Result<(), c_int>359 fn load_all_vcpus(&mut self) -> result::Result<(), c_int> {
360 let mut r = MainRequest::new();
361 r.mut_get_vcpus();
362 let (_, mut files) = self.main_transaction(&r, &[])?;
363 if files.is_empty() || files.len() % 2 != 0 {
364 return Err(EPROTO);
365 }
366
367 let mut vcpus = Vec::with_capacity(files.len() / 2);
368 while files.len() > 1 {
369 let write_pipe = files.remove(0);
370 let read_pipe = files.remove(0);
371 vcpus.push(crosvm_vcpu::new(fd_cast(read_pipe), fd_cast(write_pipe)));
372 }
373 // Only called once by the `from_connection` constructor, which makes a new unique
374 // `self.vcpus`.
375 let self_vcpus = Arc::get_mut(&mut self.vcpus).unwrap();
376 *self_vcpus = vcpus;
377 Ok(())
378 }
379
get_shutdown_eventfd(&mut self) -> result::Result<File, c_int>380 fn get_shutdown_eventfd(&mut self) -> result::Result<File, c_int> {
381 let mut r = MainRequest::new();
382 r.mut_get_shutdown_eventfd();
383 let (_, mut files) = self.main_transaction(&r, &[])?;
384 match files.pop() {
385 Some(f) => Ok(f),
386 None => Err(EPROTO),
387 }
388 }
389
check_extension(&mut self, extension: u32) -> result::Result<bool, c_int>390 fn check_extension(&mut self, extension: u32) -> result::Result<bool, c_int> {
391 let mut r = MainRequest::new();
392 r.mut_check_extension().extension = extension;
393 let (response, _) = self.main_transaction(&r, &[])?;
394 if !response.has_check_extension() {
395 return Err(EPROTO);
396 }
397 Ok(response.get_check_extension().has_extension)
398 }
399
get_supported_cpuid( &mut self, cpuid_entries: &mut [kvm_cpuid_entry2], cpuid_count: &mut usize, ) -> result::Result<(), c_int>400 fn get_supported_cpuid(
401 &mut self,
402 cpuid_entries: &mut [kvm_cpuid_entry2],
403 cpuid_count: &mut usize,
404 ) -> result::Result<(), c_int> {
405 *cpuid_count = 0;
406
407 let mut r = MainRequest::new();
408 r.mut_get_supported_cpuid();
409
410 let (response, _) = self.main_transaction(&r, &[])?;
411 if !response.has_get_supported_cpuid() {
412 return Err(EPROTO);
413 }
414
415 let supported_cpuids: &MainResponse_CpuidResponse = response.get_get_supported_cpuid();
416
417 *cpuid_count = supported_cpuids.get_entries().len();
418 if *cpuid_count > cpuid_entries.len() {
419 return Err(E2BIG);
420 }
421
422 for (proto_entry, kvm_entry) in supported_cpuids
423 .get_entries()
424 .iter()
425 .zip(cpuid_entries.iter_mut())
426 {
427 *kvm_entry = cpuid_proto_to_kvm(proto_entry);
428 }
429
430 Ok(())
431 }
432
get_emulated_cpuid( &mut self, cpuid_entries: &mut [kvm_cpuid_entry2], cpuid_count: &mut usize, ) -> result::Result<(), c_int>433 fn get_emulated_cpuid(
434 &mut self,
435 cpuid_entries: &mut [kvm_cpuid_entry2],
436 cpuid_count: &mut usize,
437 ) -> result::Result<(), c_int> {
438 *cpuid_count = 0;
439
440 let mut r = MainRequest::new();
441 r.mut_get_emulated_cpuid();
442
443 let (response, _) = self.main_transaction(&r, &[])?;
444 if !response.has_get_emulated_cpuid() {
445 return Err(EPROTO);
446 }
447
448 let emulated_cpuids: &MainResponse_CpuidResponse = response.get_get_emulated_cpuid();
449
450 *cpuid_count = emulated_cpuids.get_entries().len();
451 if *cpuid_count > cpuid_entries.len() {
452 return Err(E2BIG);
453 }
454
455 for (proto_entry, kvm_entry) in emulated_cpuids
456 .get_entries()
457 .iter()
458 .zip(cpuid_entries.iter_mut())
459 {
460 *kvm_entry = cpuid_proto_to_kvm(proto_entry);
461 }
462
463 Ok(())
464 }
465
get_msr_index_list( &mut self, msr_indices: &mut [u32], msr_count: &mut usize, ) -> result::Result<(), c_int>466 fn get_msr_index_list(
467 &mut self,
468 msr_indices: &mut [u32],
469 msr_count: &mut usize,
470 ) -> result::Result<(), c_int> {
471 *msr_count = 0;
472
473 let mut r = MainRequest::new();
474 r.mut_get_msr_index_list();
475
476 let (response, _) = self.main_transaction(&r, &[])?;
477 if !response.has_get_msr_index_list() {
478 return Err(EPROTO);
479 }
480
481 let msr_list: &MainResponse_MsrListResponse = response.get_get_msr_index_list();
482
483 *msr_count = msr_list.get_indices().len();
484 if *msr_count > msr_indices.len() {
485 return Err(E2BIG);
486 }
487
488 for (proto_entry, kvm_entry) in msr_list.get_indices().iter().zip(msr_indices.iter_mut()) {
489 *kvm_entry = *proto_entry;
490 }
491
492 Ok(())
493 }
494
reserve_range(&mut self, space: u32, start: u64, length: u64) -> result::Result<(), c_int>495 fn reserve_range(&mut self, space: u32, start: u64, length: u64) -> result::Result<(), c_int> {
496 let mut r = MainRequest::new();
497 let reserve: &mut MainRequest_ReserveRange = r.mut_reserve_range();
498 reserve.space = AddressSpace::from_i32(space as i32).ok_or(EINVAL)?;
499 reserve.start = start;
500 reserve.length = length;
501
502 self.main_transaction(&r, &[])?;
503 Ok(())
504 }
505
set_irq(&mut self, irq_id: u32, active: bool) -> result::Result<(), c_int>506 fn set_irq(&mut self, irq_id: u32, active: bool) -> result::Result<(), c_int> {
507 let mut r = MainRequest::new();
508 let set_irq: &mut MainRequest_SetIrq = r.mut_set_irq();
509 set_irq.irq_id = irq_id;
510 set_irq.active = active;
511
512 self.main_transaction(&r, &[])?;
513 Ok(())
514 }
515
set_irq_routing(&mut self, routing: &[crosvm_irq_route]) -> result::Result<(), c_int>516 fn set_irq_routing(&mut self, routing: &[crosvm_irq_route]) -> result::Result<(), c_int> {
517 let mut r = MainRequest::new();
518 let set_irq_routing: &mut RepeatedField<MainRequest_SetIrqRouting_Route> =
519 r.mut_set_irq_routing().mut_routes();
520 for route in routing {
521 let mut entry = MainRequest_SetIrqRouting_Route::new();
522 entry.irq_id = route.irq_id;
523 match route.kind {
524 CROSVM_IRQ_ROUTE_IRQCHIP => {
525 let irqchip: &mut MainRequest_SetIrqRouting_Route_Irqchip;
526 irqchip = entry.mut_irqchip();
527 // Safe because route.kind indicates which union field is valid.
528 irqchip.irqchip = unsafe { route.route.irqchip }.irqchip;
529 irqchip.pin = unsafe { route.route.irqchip }.pin;
530 }
531 CROSVM_IRQ_ROUTE_MSI => {
532 let msi: &mut MainRequest_SetIrqRouting_Route_Msi = entry.mut_msi();
533 // Safe because route.kind indicates which union field is valid.
534 msi.address = unsafe { route.route.msi }.address;
535 msi.data = unsafe { route.route.msi }.data;
536 }
537 _ => return Err(EINVAL),
538 }
539 set_irq_routing.push(entry);
540 }
541
542 self.main_transaction(&r, &[])?;
543 Ok(())
544 }
545
get_state( &mut self, state_set: MainRequest_StateSet, out: &mut [u8], ) -> result::Result<(), c_int>546 fn get_state(
547 &mut self,
548 state_set: MainRequest_StateSet,
549 out: &mut [u8],
550 ) -> result::Result<(), c_int> {
551 let mut r = MainRequest::new();
552 r.mut_get_state().set = state_set;
553 let (response, _) = self.main_transaction(&r, &[])?;
554 if !response.has_get_state() {
555 return Err(EPROTO);
556 }
557 let get_state: &MainResponse_GetState = response.get_get_state();
558 if get_state.state.len() != out.len() {
559 return Err(EPROTO);
560 }
561 out.copy_from_slice(&get_state.state);
562 Ok(())
563 }
564
set_state( &mut self, state_set: MainRequest_StateSet, new_state: &[u8], ) -> result::Result<(), c_int>565 fn set_state(
566 &mut self,
567 state_set: MainRequest_StateSet,
568 new_state: &[u8],
569 ) -> result::Result<(), c_int> {
570 let mut r = MainRequest::new();
571 let set_state: &mut MainRequest_SetState = r.mut_set_state();
572 set_state.set = state_set;
573 set_state.state = new_state.to_vec();
574
575 self.main_transaction(&r, &[])?;
576 Ok(())
577 }
578
set_identity_map_addr(&mut self, addr: u32) -> result::Result<(), c_int>579 fn set_identity_map_addr(&mut self, addr: u32) -> result::Result<(), c_int> {
580 let mut r = MainRequest::new();
581 r.mut_set_identity_map_addr().address = addr;
582
583 self.main_transaction(&r, &[])?;
584 Ok(())
585 }
586
pause_vcpus(&mut self, cpu_mask: u64, user: *mut c_void) -> result::Result<(), c_int>587 fn pause_vcpus(&mut self, cpu_mask: u64, user: *mut c_void) -> result::Result<(), c_int> {
588 let mut r = MainRequest::new();
589 let pause_vcpus: &mut MainRequest_PauseVcpus = r.mut_pause_vcpus();
590 pause_vcpus.cpu_mask = cpu_mask;
591 pause_vcpus.user = user as u64;
592 self.main_transaction(&r, &[])?;
593 Ok(())
594 }
595
start(&mut self) -> result::Result<(), c_int>596 fn start(&mut self) -> result::Result<(), c_int> {
597 let mut r = MainRequest::new();
598 r.mut_start();
599 self.main_transaction(&r, &[])?;
600 Ok(())
601 }
602
get_vcpu(&mut self, cpu_id: u32) -> Result<*mut crosvm_vcpu, c_int>603 fn get_vcpu(&mut self, cpu_id: u32) -> Result<*mut crosvm_vcpu, c_int> {
604 if let Some(vcpu) = self.vcpus.get(cpu_id as usize) {
605 Ok(vcpu as *const crosvm_vcpu as *mut crosvm_vcpu)
606 } else {
607 Err(ENOENT)
608 }
609 }
610
get_net_config(&mut self) -> result::Result<crosvm_net_config, c_int>611 fn get_net_config(&mut self) -> result::Result<crosvm_net_config, c_int> {
612 let mut r = MainRequest::new();
613 r.mut_get_net_config();
614
615 let (response, mut files) = self.main_transaction(&r, &[])?;
616 if !response.has_get_net_config() {
617 return Err(EPROTO);
618 }
619 let config = response.get_get_net_config();
620
621 match files.pop() {
622 Some(f) => {
623 let mut net_config = crosvm_net_config {
624 tap_fd: f.into_raw_fd(),
625 host_ipv4_address: config.host_ipv4_address,
626 netmask: config.netmask,
627 host_mac_address: [0; 6],
628 _reserved: [0; 2],
629 };
630
631 let mac_addr = config.get_host_mac_address();
632 if mac_addr.len() != net_config.host_mac_address.len() {
633 return Err(EPROTO);
634 }
635 net_config.host_mac_address.copy_from_slice(mac_addr);
636
637 Ok(net_config)
638 }
639 None => Err(EPROTO),
640 }
641 }
642 }
643
644 /// This helper macro implements the C API's constructor/destructor for a given type. Because they
645 /// all follow the same pattern and include lots of boilerplate unsafe code, it makes sense to write
646 /// it once with this helper macro.
647 macro_rules! impl_ctor_dtor {
648 (
649 $t:ident,
650 $ctor:ident ( $( $x:ident: $y:ty ),* ),
651 $dtor:ident,
652 ) => {
653 #[allow(unused_unsafe)]
654 #[no_mangle]
655 pub unsafe extern fn $ctor(self_: *mut crosvm, $($x: $y,)* obj_ptr: *mut *mut $t) -> c_int {
656 let self_ = &mut (*self_);
657 match $t::create(self_, $($x,)*) {
658 Ok(obj) => {
659 *obj_ptr = Box::into_raw(Box::new(obj));
660 0
661 }
662 Err(e) => -e,
663 }
664 }
665 #[no_mangle]
666 pub unsafe extern fn $dtor(self_: *mut crosvm, obj_ptr: *mut *mut $t) -> c_int {
667 let self_ = &mut (*self_);
668 let obj = Box::from_raw(*obj_ptr);
669 match self_.destroy(obj.id) {
670 Ok(_) => {
671 *obj_ptr = null_mut();
672 0
673 }
674 Err(e) => {
675 Box::into_raw(obj);
676 -e
677 }
678 }
679 }
680 }
681 }
682
683 pub struct crosvm_io_event {
684 id: u32,
685 evt: File,
686 }
687
688 impl crosvm_io_event {
689 // Clippy: we use ptr::read_unaligned to read from pointers that may be
690 // underaligned. Dereferencing such a pointer is always undefined behavior
691 // in Rust.
692 //
693 // Lint can be unsuppressed once Clippy recognizes this pattern as correct.
694 // https://github.com/rust-lang/rust-clippy/issues/2881
695 #[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>696 unsafe fn create(
697 crosvm: &mut crosvm,
698 space: u32,
699 addr: u64,
700 length: u32,
701 datamatch: *const u8,
702 ) -> result::Result<crosvm_io_event, c_int> {
703 let datamatch = match length {
704 0 => 0,
705 1 => ptr::read_unaligned(datamatch as *const u8) as u64,
706 2 => ptr::read_unaligned(datamatch as *const u16) as u64,
707 4 => ptr::read_unaligned(datamatch as *const u32) as u64,
708 8 => ptr::read_unaligned(datamatch as *const u64),
709 _ => return Err(EINVAL),
710 };
711 Self::safe_create(crosvm, space, addr, length, datamatch)
712 }
713
safe_create( crosvm: &mut crosvm, space: u32, addr: u64, length: u32, datamatch: u64, ) -> result::Result<crosvm_io_event, c_int>714 fn safe_create(
715 crosvm: &mut crosvm,
716 space: u32,
717 addr: u64,
718 length: u32,
719 datamatch: u64,
720 ) -> result::Result<crosvm_io_event, c_int> {
721 let id = crosvm.get_id_allocator().alloc();
722
723 let mut r = MainRequest::new();
724 let create: &mut MainRequest_Create = r.mut_create();
725 create.id = id;
726 let io_event: &mut MainRequest_Create_IoEvent = create.mut_io_event();
727 io_event.space = AddressSpace::from_i32(space as i32).ok_or(EINVAL)?;
728 io_event.address = addr;
729 io_event.length = length;
730 io_event.datamatch = datamatch;
731
732 let ret = match crosvm.main_transaction(&r, &[]) {
733 Ok((_, mut files)) => match files.pop() {
734 Some(evt) => return Ok(crosvm_io_event { id, evt }),
735 None => EPROTO,
736 },
737 Err(e) => e,
738 };
739 crosvm.get_id_allocator().free(id);
740 Err(ret)
741 }
742 }
743
744 impl_ctor_dtor!(
745 crosvm_io_event,
746 crosvm_create_io_event(space: u32, addr: u64, len: u32, datamatch: *const u8),
747 crosvm_destroy_io_event,
748 );
749
750 #[no_mangle]
crosvm_io_event_fd(this: *mut crosvm_io_event) -> c_int751 pub unsafe extern "C" fn crosvm_io_event_fd(this: *mut crosvm_io_event) -> c_int {
752 let _u = STATS.record(Stat::IoEventFd);
753 (*this).evt.as_raw_fd()
754 }
755
756 pub struct crosvm_memory {
757 id: u32,
758 length: u64,
759 }
760
761 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>762 fn create(
763 crosvm: &mut crosvm,
764 fd: c_int,
765 offset: u64,
766 length: u64,
767 start: u64,
768 read_only: bool,
769 dirty_log: bool,
770 ) -> result::Result<crosvm_memory, c_int> {
771 const PAGE_MASK: u64 = 0x0fff;
772 if offset & PAGE_MASK != 0 || length & PAGE_MASK != 0 {
773 return Err(EINVAL);
774 }
775 let id = crosvm.get_id_allocator().alloc();
776
777 let mut r = MainRequest::new();
778 let create: &mut MainRequest_Create = r.mut_create();
779 create.id = id;
780 let memory: &mut MainRequest_Create_Memory = create.mut_memory();
781 memory.offset = offset;
782 memory.start = start;
783 memory.length = length;
784 memory.read_only = read_only;
785 memory.dirty_log = dirty_log;
786
787 let ret = match crosvm.main_transaction(&r, &[fd]) {
788 Ok(_) => return Ok(crosvm_memory { id, length }),
789 Err(e) => e,
790 };
791 crosvm.get_id_allocator().free(id);
792 Err(ret)
793 }
794
get_dirty_log(&mut self, crosvm: &mut crosvm) -> result::Result<Vec<u8>, c_int>795 fn get_dirty_log(&mut self, crosvm: &mut crosvm) -> result::Result<Vec<u8>, c_int> {
796 let mut r = MainRequest::new();
797 r.mut_dirty_log().id = self.id;
798 let (mut response, _) = crosvm.main_transaction(&r, &[])?;
799 if !response.has_dirty_log() {
800 return Err(EPROTO);
801 }
802 Ok(response.take_dirty_log().bitmap)
803 }
804 }
805
806 impl_ctor_dtor!(
807 crosvm_memory,
808 crosvm_create_memory(
809 fd: c_int,
810 offset: u64,
811 length: u64,
812 start: u64,
813 read_only: bool,
814 dirty_log: bool
815 ),
816 crosvm_destroy_memory,
817 );
818
819 #[no_mangle]
crosvm_memory_get_dirty_log( crosvm: *mut crosvm, this: *mut crosvm_memory, log: *mut u8, ) -> c_int820 pub unsafe extern "C" fn crosvm_memory_get_dirty_log(
821 crosvm: *mut crosvm,
822 this: *mut crosvm_memory,
823 log: *mut u8,
824 ) -> c_int {
825 let _u = STATS.record(Stat::MemoryGetDirtyLog);
826 let crosvm = &mut *crosvm;
827 let this = &mut *this;
828 let log_slice = slice::from_raw_parts_mut(log, dirty_log_bitmap_size(this.length as usize));
829 match this.get_dirty_log(crosvm) {
830 Ok(bitmap) => {
831 if bitmap.len() == log_slice.len() {
832 log_slice.copy_from_slice(&bitmap);
833 0
834 } else {
835 -EPROTO
836 }
837 }
838 Err(e) => -e,
839 }
840 }
841
842 pub struct crosvm_irq_event {
843 id: u32,
844 trigger_evt: File,
845 resample_evt: File,
846 }
847
848 impl crosvm_irq_event {
create(crosvm: &mut crosvm, irq_id: u32) -> result::Result<crosvm_irq_event, c_int>849 fn create(crosvm: &mut crosvm, irq_id: u32) -> result::Result<crosvm_irq_event, c_int> {
850 let id = crosvm.get_id_allocator().alloc();
851
852 let mut r = MainRequest::new();
853 let create: &mut MainRequest_Create = r.mut_create();
854 create.id = id;
855 let irq_event: &mut MainRequest_Create_IrqEvent = create.mut_irq_event();
856 irq_event.irq_id = irq_id;
857 irq_event.resample = true;
858
859 let ret = match crosvm.main_transaction(&r, &[]) {
860 Ok((_, mut files)) => {
861 if files.len() >= 2 {
862 let resample_evt = files.pop().unwrap();
863 let trigger_evt = files.pop().unwrap();
864 return Ok(crosvm_irq_event {
865 id,
866 trigger_evt,
867 resample_evt,
868 });
869 }
870 EPROTO
871 }
872 Err(e) => e,
873 };
874 crosvm.get_id_allocator().free(id);
875 Err(ret)
876 }
877 }
878
879 impl_ctor_dtor!(
880 crosvm_irq_event,
881 crosvm_create_irq_event(irq_id: u32),
882 crosvm_destroy_irq_event,
883 );
884
885 #[no_mangle]
crosvm_irq_event_get_fd(this: *mut crosvm_irq_event) -> c_int886 pub unsafe extern "C" fn crosvm_irq_event_get_fd(this: *mut crosvm_irq_event) -> c_int {
887 let _u = STATS.record(Stat::IrqEventGetFd);
888 (*this).trigger_evt.as_raw_fd()
889 }
890
891 #[no_mangle]
crosvm_irq_event_get_resample_fd(this: *mut crosvm_irq_event) -> c_int892 pub unsafe extern "C" fn crosvm_irq_event_get_resample_fd(this: *mut crosvm_irq_event) -> c_int {
893 let _u = STATS.record(Stat::IrqEventGetResampleFd);
894 (*this).resample_evt.as_raw_fd()
895 }
896
897 #[allow(dead_code)]
898 #[derive(Copy, Clone)]
899 #[repr(C)]
900 struct anon_io_access {
901 address_space: u32,
902 __reserved0: [u8; 4],
903 address: u64,
904 data: *mut u8,
905 length: u32,
906 is_write: u8,
907 __reserved1: u8,
908 }
909
910 #[repr(C)]
911 union anon_vcpu_event {
912 io_access: anon_io_access,
913 user: *mut c_void,
914 #[allow(dead_code)]
915 __reserved: [u8; 64],
916 }
917
918 #[repr(C)]
919 pub struct crosvm_vcpu_event {
920 kind: u32,
921 __reserved: [u8; 4],
922 event: anon_vcpu_event,
923 }
924
925 pub struct crosvm_vcpu {
926 read_pipe: File,
927 write_pipe: File,
928 send_init: bool,
929 request_buffer: Vec<u8>,
930 response_buffer: Vec<u8>,
931 resume_data: Vec<u8>,
932 }
933
934 impl crosvm_vcpu {
new(read_pipe: File, write_pipe: File) -> crosvm_vcpu935 fn new(read_pipe: File, write_pipe: File) -> crosvm_vcpu {
936 crosvm_vcpu {
937 read_pipe,
938 write_pipe,
939 send_init: true,
940 request_buffer: Vec::new(),
941 response_buffer: vec![0; MAX_DATAGRAM_SIZE],
942 resume_data: Vec::new(),
943 }
944 }
vcpu_send(&mut self, request: &VcpuRequest) -> result::Result<(), c_int>945 fn vcpu_send(&mut self, request: &VcpuRequest) -> result::Result<(), c_int> {
946 self.request_buffer.clear();
947 request
948 .write_to_vec(&mut self.request_buffer)
949 .map_err(proto_error_to_int)?;
950 self.write_pipe
951 .write(self.request_buffer.as_slice())
952 .map_err(|e| -e.raw_os_error().unwrap_or(EINVAL))?;
953 Ok(())
954 }
955
vcpu_recv(&mut self) -> result::Result<VcpuResponse, c_int>956 fn vcpu_recv(&mut self) -> result::Result<VcpuResponse, c_int> {
957 let msg_size = self
958 .read_pipe
959 .read(&mut self.response_buffer)
960 .map_err(|e| -e.raw_os_error().unwrap_or(EINVAL))?;
961
962 let response: VcpuResponse =
963 parse_from_bytes(&self.response_buffer[..msg_size]).map_err(proto_error_to_int)?;
964 if response.errno != 0 {
965 return Err(response.errno);
966 }
967 Ok(response)
968 }
969
vcpu_transaction(&mut self, request: &VcpuRequest) -> result::Result<VcpuResponse, c_int>970 fn vcpu_transaction(&mut self, request: &VcpuRequest) -> result::Result<VcpuResponse, c_int> {
971 self.vcpu_send(request)?;
972 let response: VcpuResponse = self.vcpu_recv()?;
973 Ok(response)
974 }
975
wait(&mut self, event: &mut crosvm_vcpu_event) -> result::Result<(), c_int>976 fn wait(&mut self, event: &mut crosvm_vcpu_event) -> result::Result<(), c_int> {
977 if self.send_init {
978 self.send_init = false;
979 let mut r = VcpuRequest::new();
980 r.mut_wait();
981 self.vcpu_send(&r)?;
982 }
983 let mut response: VcpuResponse = self.vcpu_recv()?;
984 if !response.has_wait() {
985 return Err(EPROTO);
986 }
987 let wait: &mut VcpuResponse_Wait = response.mut_wait();
988 if wait.has_init() {
989 event.kind = CROSVM_VCPU_EVENT_KIND_INIT;
990 Ok(())
991 } else if wait.has_io() {
992 let mut io: VcpuResponse_Wait_Io = wait.take_io();
993 event.kind = CROSVM_VCPU_EVENT_KIND_IO_ACCESS;
994 event.event.io_access = anon_io_access {
995 address_space: io.space.value() as u32,
996 __reserved0: Default::default(),
997 address: io.address,
998 data: io.data.as_mut_ptr(),
999 length: io.data.len() as u32,
1000 is_write: io.is_write as u8,
1001 __reserved1: Default::default(),
1002 };
1003 self.resume_data = io.data;
1004 Ok(())
1005 } else if wait.has_user() {
1006 let user: &VcpuResponse_Wait_User = wait.get_user();
1007 event.kind = CROSVM_VCPU_EVENT_KIND_PAUSED;
1008 event.event.user = user.user as *mut c_void;
1009 Ok(())
1010 } else {
1011 Err(EPROTO)
1012 }
1013 }
1014
resume(&mut self) -> result::Result<(), c_int>1015 fn resume(&mut self) -> result::Result<(), c_int> {
1016 let mut r = VcpuRequest::new();
1017 let resume: &mut VcpuRequest_Resume = r.mut_resume();
1018 swap(&mut resume.data, &mut self.resume_data);
1019
1020 self.vcpu_send(&r)?;
1021 Ok(())
1022 }
1023
get_state( &mut self, state_set: VcpuRequest_StateSet, out: &mut [u8], ) -> result::Result<(), c_int>1024 fn get_state(
1025 &mut self,
1026 state_set: VcpuRequest_StateSet,
1027 out: &mut [u8],
1028 ) -> result::Result<(), c_int> {
1029 let mut r = VcpuRequest::new();
1030 r.mut_get_state().set = state_set;
1031 let response = self.vcpu_transaction(&r)?;
1032 if !response.has_get_state() {
1033 return Err(EPROTO);
1034 }
1035 let get_state: &VcpuResponse_GetState = response.get_get_state();
1036 if get_state.state.len() != out.len() {
1037 return Err(EPROTO);
1038 }
1039 out.copy_from_slice(&get_state.state);
1040 Ok(())
1041 }
1042
set_state( &mut self, state_set: VcpuRequest_StateSet, new_state: &[u8], ) -> result::Result<(), c_int>1043 fn set_state(
1044 &mut self,
1045 state_set: VcpuRequest_StateSet,
1046 new_state: &[u8],
1047 ) -> result::Result<(), c_int> {
1048 let mut r = VcpuRequest::new();
1049 let set_state: &mut VcpuRequest_SetState = r.mut_set_state();
1050 set_state.set = state_set;
1051 set_state.state = new_state.to_vec();
1052
1053 self.vcpu_transaction(&r)?;
1054 Ok(())
1055 }
1056
get_msrs( &mut self, msr_entries: &mut [kvm_msr_entry], msr_count: &mut usize, ) -> result::Result<(), c_int>1057 fn get_msrs(
1058 &mut self,
1059 msr_entries: &mut [kvm_msr_entry],
1060 msr_count: &mut usize,
1061 ) -> result::Result<(), c_int> {
1062 *msr_count = 0;
1063
1064 let mut r = VcpuRequest::new();
1065 let entry_indices: &mut Vec<u32> = r.mut_get_msrs().mut_entry_indices();
1066 for entry in msr_entries.iter() {
1067 entry_indices.push(entry.index);
1068 }
1069
1070 let response = self.vcpu_transaction(&r)?;
1071 if !response.has_get_msrs() {
1072 return Err(EPROTO);
1073 }
1074 let get_msrs: &VcpuResponse_GetMsrs = response.get_get_msrs();
1075 *msr_count = get_msrs.get_entry_data().len();
1076 if *msr_count > msr_entries.len() {
1077 return Err(E2BIG);
1078 }
1079 for (&msr_data, msr_entry) in get_msrs.get_entry_data().iter().zip(msr_entries) {
1080 msr_entry.data = msr_data;
1081 }
1082 Ok(())
1083 }
1084
set_msrs(&mut self, msr_entries: &[kvm_msr_entry]) -> result::Result<(), c_int>1085 fn set_msrs(&mut self, msr_entries: &[kvm_msr_entry]) -> result::Result<(), c_int> {
1086 let mut r = VcpuRequest::new();
1087 let set_msrs_entries: &mut RepeatedField<VcpuRequest_MsrEntry> =
1088 r.mut_set_msrs().mut_entries();
1089 for msr_entry in msr_entries {
1090 let mut entry = VcpuRequest_MsrEntry::new();
1091 entry.index = msr_entry.index;
1092 entry.data = msr_entry.data;
1093 set_msrs_entries.push(entry);
1094 }
1095
1096 self.vcpu_transaction(&r)?;
1097 Ok(())
1098 }
1099
set_cpuid(&mut self, cpuid_entries: &[kvm_cpuid_entry2]) -> result::Result<(), c_int>1100 fn set_cpuid(&mut self, cpuid_entries: &[kvm_cpuid_entry2]) -> result::Result<(), c_int> {
1101 let mut r = VcpuRequest::new();
1102 let set_cpuid_entries: &mut RepeatedField<CpuidEntry> = r.mut_set_cpuid().mut_entries();
1103 for cpuid_entry in cpuid_entries {
1104 set_cpuid_entries.push(cpuid_kvm_to_proto(cpuid_entry));
1105 }
1106
1107 self.vcpu_transaction(&r)?;
1108 Ok(())
1109 }
1110 }
1111
1112 // crosvm API signals success as 0 and errors as negative values
1113 // derived from `errno`.
to_crosvm_rc<T>(r: result::Result<T, c_int>) -> c_int1114 fn to_crosvm_rc<T>(r: result::Result<T, c_int>) -> c_int {
1115 match r {
1116 Ok(_) => 0,
1117 Err(e) => -e,
1118 }
1119 }
1120
1121 #[no_mangle]
crosvm_connect(out: *mut *mut crosvm) -> c_int1122 pub unsafe extern "C" fn crosvm_connect(out: *mut *mut crosvm) -> c_int {
1123 let _u = STATS.record(Stat::Connect);
1124 let socket_name = match env::var("CROSVM_SOCKET") {
1125 Ok(v) => v,
1126 _ => return -ENOTCONN,
1127 };
1128
1129 let socket = match socket_name.parse() {
1130 Ok(v) if v < 0 => return -EINVAL,
1131 Ok(v) => v,
1132 _ => return -EINVAL,
1133 };
1134
1135 let socket = UnixDatagram::from_raw_fd(socket);
1136 let crosvm = match crosvm::from_connection(socket) {
1137 Ok(c) => c,
1138 Err(e) => return -e,
1139 };
1140 *out = Box::into_raw(Box::new(crosvm));
1141 0
1142 }
1143
1144 #[no_mangle]
crosvm_new_connection(self_: *mut crosvm, out: *mut *mut crosvm) -> c_int1145 pub unsafe extern "C" fn crosvm_new_connection(self_: *mut crosvm, out: *mut *mut crosvm) -> c_int {
1146 let _u = STATS.record(Stat::NewConnection);
1147 let self_ = &mut (*self_);
1148 match self_.try_clone() {
1149 Ok(cloned) => {
1150 *out = Box::into_raw(Box::new(cloned));
1151 0
1152 }
1153 Err(e) => -e,
1154 }
1155 }
1156
1157 #[no_mangle]
crosvm_destroy_connection(self_: *mut *mut crosvm) -> c_int1158 pub unsafe extern "C" fn crosvm_destroy_connection(self_: *mut *mut crosvm) -> c_int {
1159 let _u = STATS.record(Stat::DestroyConnection);
1160 Box::from_raw(*self_);
1161 *self_ = null_mut();
1162 0
1163 }
1164
1165 #[no_mangle]
crosvm_get_shutdown_eventfd(self_: *mut crosvm) -> c_int1166 pub unsafe extern "C" fn crosvm_get_shutdown_eventfd(self_: *mut crosvm) -> c_int {
1167 let _u = STATS.record(Stat::GetShutdownEventFd);
1168 let self_ = &mut (*self_);
1169 match self_.get_shutdown_eventfd() {
1170 Ok(f) => f.into_raw_fd(),
1171 Err(e) => -e,
1172 }
1173 }
1174
1175 #[no_mangle]
crosvm_check_extension( self_: *mut crosvm, extension: u32, has_extension: *mut bool, ) -> c_int1176 pub unsafe extern "C" fn crosvm_check_extension(
1177 self_: *mut crosvm,
1178 extension: u32,
1179 has_extension: *mut bool,
1180 ) -> c_int {
1181 let _u = STATS.record(Stat::CheckExtentsion);
1182 let self_ = &mut (*self_);
1183 let ret = self_.check_extension(extension);
1184
1185 if let Ok(supported) = ret {
1186 *has_extension = supported;
1187 }
1188 to_crosvm_rc(ret)
1189 }
1190
1191 #[no_mangle]
crosvm_get_supported_cpuid( this: *mut crosvm, entry_count: u32, cpuid_entries: *mut kvm_cpuid_entry2, out_count: *mut u32, ) -> c_int1192 pub unsafe extern "C" fn crosvm_get_supported_cpuid(
1193 this: *mut crosvm,
1194 entry_count: u32,
1195 cpuid_entries: *mut kvm_cpuid_entry2,
1196 out_count: *mut u32,
1197 ) -> c_int {
1198 let _u = STATS.record(Stat::GetSupportedCpuid);
1199 let this = &mut *this;
1200 let cpuid_entries = from_raw_parts_mut(cpuid_entries, entry_count as usize);
1201 let mut cpuid_count: usize = 0;
1202 let ret = this.get_supported_cpuid(cpuid_entries, &mut cpuid_count);
1203 *out_count = cpuid_count as u32;
1204 to_crosvm_rc(ret)
1205 }
1206
1207 #[no_mangle]
crosvm_get_emulated_cpuid( this: *mut crosvm, entry_count: u32, cpuid_entries: *mut kvm_cpuid_entry2, out_count: *mut u32, ) -> c_int1208 pub unsafe extern "C" fn crosvm_get_emulated_cpuid(
1209 this: *mut crosvm,
1210 entry_count: u32,
1211 cpuid_entries: *mut kvm_cpuid_entry2,
1212 out_count: *mut u32,
1213 ) -> c_int {
1214 let _u = STATS.record(Stat::GetEmulatedCpuid);
1215 let this = &mut *this;
1216 let cpuid_entries = from_raw_parts_mut(cpuid_entries, entry_count as usize);
1217 let mut cpuid_count: usize = 0;
1218 let ret = this.get_emulated_cpuid(cpuid_entries, &mut cpuid_count);
1219 *out_count = cpuid_count as u32;
1220 to_crosvm_rc(ret)
1221 }
1222
1223 #[no_mangle]
crosvm_get_msr_index_list( this: *mut crosvm, entry_count: u32, msr_indices: *mut u32, out_count: *mut u32, ) -> c_int1224 pub unsafe extern "C" fn crosvm_get_msr_index_list(
1225 this: *mut crosvm,
1226 entry_count: u32,
1227 msr_indices: *mut u32,
1228 out_count: *mut u32,
1229 ) -> c_int {
1230 let _u = STATS.record(Stat::GetMsrIndexList);
1231 let this = &mut *this;
1232 let msr_indices = from_raw_parts_mut(msr_indices, entry_count as usize);
1233 let mut msr_count: usize = 0;
1234 let ret = this.get_msr_index_list(msr_indices, &mut msr_count);
1235 *out_count = msr_count as u32;
1236 to_crosvm_rc(ret)
1237 }
1238
1239 #[no_mangle]
crosvm_net_get_config( self_: *mut crosvm, config: *mut crosvm_net_config, ) -> c_int1240 pub unsafe extern "C" fn crosvm_net_get_config(
1241 self_: *mut crosvm,
1242 config: *mut crosvm_net_config,
1243 ) -> c_int {
1244 let _u = STATS.record(Stat::NetGetConfig);
1245 let self_ = &mut (*self_);
1246 let ret = self_.get_net_config();
1247
1248 if let Ok(c) = ret {
1249 *config = c;
1250 }
1251
1252 to_crosvm_rc(ret)
1253 }
1254
1255 #[no_mangle]
crosvm_reserve_range( self_: *mut crosvm, space: u32, start: u64, length: u64, ) -> c_int1256 pub unsafe extern "C" fn crosvm_reserve_range(
1257 self_: *mut crosvm,
1258 space: u32,
1259 start: u64,
1260 length: u64,
1261 ) -> c_int {
1262 let _u = STATS.record(Stat::ReserveRange);
1263 let self_ = &mut (*self_);
1264 let ret = self_.reserve_range(space, start, length);
1265 to_crosvm_rc(ret)
1266 }
1267
1268 #[no_mangle]
crosvm_set_irq(self_: *mut crosvm, irq_id: u32, active: bool) -> c_int1269 pub unsafe extern "C" fn crosvm_set_irq(self_: *mut crosvm, irq_id: u32, active: bool) -> c_int {
1270 let _u = STATS.record(Stat::SetIrq);
1271 let self_ = &mut (*self_);
1272 let ret = self_.set_irq(irq_id, active);
1273 to_crosvm_rc(ret)
1274 }
1275
1276 #[no_mangle]
crosvm_set_irq_routing( self_: *mut crosvm, route_count: u32, routes: *const crosvm_irq_route, ) -> c_int1277 pub unsafe extern "C" fn crosvm_set_irq_routing(
1278 self_: *mut crosvm,
1279 route_count: u32,
1280 routes: *const crosvm_irq_route,
1281 ) -> c_int {
1282 let _u = STATS.record(Stat::SetIrqRouting);
1283 let self_ = &mut (*self_);
1284 let ret = self_.set_irq_routing(slice::from_raw_parts(routes, route_count as usize));
1285 to_crosvm_rc(ret)
1286 }
1287
1288 #[no_mangle]
crosvm_get_pic_state( this: *mut crosvm, primary: bool, state: *mut kvm_pic_state, ) -> c_int1289 pub unsafe extern "C" fn crosvm_get_pic_state(
1290 this: *mut crosvm,
1291 primary: bool,
1292 state: *mut kvm_pic_state,
1293 ) -> c_int {
1294 let _u = STATS.record(Stat::GetPicState);
1295 let this = &mut *this;
1296 let state_set = if primary {
1297 MainRequest_StateSet::PIC0
1298 } else {
1299 MainRequest_StateSet::PIC1
1300 };
1301 let state = from_raw_parts_mut(state as *mut u8, size_of::<kvm_pic_state>());
1302 let ret = this.get_state(state_set, state);
1303 to_crosvm_rc(ret)
1304 }
1305
1306 #[no_mangle]
crosvm_set_pic_state( this: *mut crosvm, primary: bool, state: *mut kvm_pic_state, ) -> c_int1307 pub unsafe extern "C" fn crosvm_set_pic_state(
1308 this: *mut crosvm,
1309 primary: bool,
1310 state: *mut kvm_pic_state,
1311 ) -> c_int {
1312 let _u = STATS.record(Stat::SetPicState);
1313 let this = &mut *this;
1314 let state_set = if primary {
1315 MainRequest_StateSet::PIC0
1316 } else {
1317 MainRequest_StateSet::PIC1
1318 };
1319 let state = from_raw_parts(state as *mut u8, size_of::<kvm_pic_state>());
1320 let ret = this.set_state(state_set, state);
1321 to_crosvm_rc(ret)
1322 }
1323
1324 #[no_mangle]
crosvm_get_ioapic_state( this: *mut crosvm, state: *mut kvm_ioapic_state, ) -> c_int1325 pub unsafe extern "C" fn crosvm_get_ioapic_state(
1326 this: *mut crosvm,
1327 state: *mut kvm_ioapic_state,
1328 ) -> c_int {
1329 let _u = STATS.record(Stat::GetIoapicState);
1330 let this = &mut *this;
1331 let state = from_raw_parts_mut(state as *mut u8, size_of::<kvm_ioapic_state>());
1332 let ret = this.get_state(MainRequest_StateSet::IOAPIC, state);
1333 to_crosvm_rc(ret)
1334 }
1335
1336 #[no_mangle]
crosvm_set_ioapic_state( this: *mut crosvm, state: *const kvm_ioapic_state, ) -> c_int1337 pub unsafe extern "C" fn crosvm_set_ioapic_state(
1338 this: *mut crosvm,
1339 state: *const kvm_ioapic_state,
1340 ) -> c_int {
1341 let _u = STATS.record(Stat::SetIoapicState);
1342 let this = &mut *this;
1343 let state = from_raw_parts(state as *mut u8, size_of::<kvm_ioapic_state>());
1344 let ret = this.set_state(MainRequest_StateSet::IOAPIC, state);
1345 to_crosvm_rc(ret)
1346 }
1347
1348 #[no_mangle]
crosvm_get_pit_state( this: *mut crosvm, state: *mut kvm_pit_state2, ) -> c_int1349 pub unsafe extern "C" fn crosvm_get_pit_state(
1350 this: *mut crosvm,
1351 state: *mut kvm_pit_state2,
1352 ) -> c_int {
1353 let _u = STATS.record(Stat::GetPitState);
1354 let this = &mut *this;
1355 let state = from_raw_parts_mut(state as *mut u8, size_of::<kvm_pit_state2>());
1356 let ret = this.get_state(MainRequest_StateSet::PIT, state);
1357 to_crosvm_rc(ret)
1358 }
1359
1360 #[no_mangle]
crosvm_set_pit_state( this: *mut crosvm, state: *const kvm_pit_state2, ) -> c_int1361 pub unsafe extern "C" fn crosvm_set_pit_state(
1362 this: *mut crosvm,
1363 state: *const kvm_pit_state2,
1364 ) -> c_int {
1365 let _u = STATS.record(Stat::SetPitState);
1366 let this = &mut *this;
1367 let state = from_raw_parts(state as *mut u8, size_of::<kvm_pit_state2>());
1368 let ret = this.set_state(MainRequest_StateSet::PIT, state);
1369 to_crosvm_rc(ret)
1370 }
1371
1372 #[no_mangle]
crosvm_get_clock( this: *mut crosvm, clock_data: *mut kvm_clock_data, ) -> c_int1373 pub unsafe extern "C" fn crosvm_get_clock(
1374 this: *mut crosvm,
1375 clock_data: *mut kvm_clock_data,
1376 ) -> c_int {
1377 let _u = STATS.record(Stat::GetClock);
1378 let this = &mut *this;
1379 let state = from_raw_parts_mut(clock_data as *mut u8, size_of::<kvm_clock_data>());
1380 let ret = this.get_state(MainRequest_StateSet::CLOCK, state);
1381 to_crosvm_rc(ret)
1382 }
1383
1384 #[no_mangle]
crosvm_set_clock( this: *mut crosvm, clock_data: *const kvm_clock_data, ) -> c_int1385 pub unsafe extern "C" fn crosvm_set_clock(
1386 this: *mut crosvm,
1387 clock_data: *const kvm_clock_data,
1388 ) -> c_int {
1389 let _u = STATS.record(Stat::SetClock);
1390 let this = &mut *this;
1391 let state = from_raw_parts(clock_data as *mut u8, size_of::<kvm_clock_data>());
1392 let ret = this.set_state(MainRequest_StateSet::CLOCK, state);
1393 to_crosvm_rc(ret)
1394 }
1395
1396 #[no_mangle]
crosvm_set_identity_map_addr(self_: *mut crosvm, addr: u32) -> c_int1397 pub unsafe extern "C" fn crosvm_set_identity_map_addr(self_: *mut crosvm, addr: u32) -> c_int {
1398 let _u = STATS.record(Stat::SetIdentityMapAddr);
1399 let self_ = &mut (*self_);
1400 let ret = self_.set_identity_map_addr(addr);
1401 to_crosvm_rc(ret)
1402 }
1403
1404 #[no_mangle]
crosvm_pause_vcpus( self_: *mut crosvm, cpu_mask: u64, user: *mut c_void, ) -> c_int1405 pub unsafe extern "C" fn crosvm_pause_vcpus(
1406 self_: *mut crosvm,
1407 cpu_mask: u64,
1408 user: *mut c_void,
1409 ) -> c_int {
1410 let _u = STATS.record(Stat::PauseVcpus);
1411 let self_ = &mut (*self_);
1412 let ret = self_.pause_vcpus(cpu_mask, user);
1413 to_crosvm_rc(ret)
1414 }
1415
1416 #[no_mangle]
crosvm_start(self_: *mut crosvm) -> c_int1417 pub unsafe extern "C" fn crosvm_start(self_: *mut crosvm) -> c_int {
1418 let _u = STATS.record(Stat::Start);
1419 let self_ = &mut (*self_);
1420 let ret = self_.start();
1421 to_crosvm_rc(ret)
1422 }
1423
1424 #[no_mangle]
crosvm_get_vcpu( self_: *mut crosvm, cpu_id: u32, out: *mut *mut crosvm_vcpu, ) -> c_int1425 pub unsafe extern "C" fn crosvm_get_vcpu(
1426 self_: *mut crosvm,
1427 cpu_id: u32,
1428 out: *mut *mut crosvm_vcpu,
1429 ) -> c_int {
1430 let _u = STATS.record(Stat::GetVcpu);
1431 let self_ = &mut (*self_);
1432 let ret = self_.get_vcpu(cpu_id);
1433
1434 if let Ok(vcpu) = ret {
1435 *out = vcpu;
1436 }
1437 to_crosvm_rc(ret)
1438 }
1439
1440 #[no_mangle]
crosvm_vcpu_wait( this: *mut crosvm_vcpu, event: *mut crosvm_vcpu_event, ) -> c_int1441 pub unsafe extern "C" fn crosvm_vcpu_wait(
1442 this: *mut crosvm_vcpu,
1443 event: *mut crosvm_vcpu_event,
1444 ) -> c_int {
1445 let _u = STATS.record(Stat::VcpuWait);
1446 let this = &mut *this;
1447 let event = &mut *event;
1448 let ret = this.wait(event);
1449 to_crosvm_rc(ret)
1450 }
1451
1452 #[no_mangle]
crosvm_vcpu_resume(this: *mut crosvm_vcpu) -> c_int1453 pub unsafe extern "C" fn crosvm_vcpu_resume(this: *mut crosvm_vcpu) -> c_int {
1454 let _u = STATS.record(Stat::VcpuResume);
1455 let this = &mut *this;
1456 let ret = this.resume();
1457 to_crosvm_rc(ret)
1458 }
1459
1460 #[no_mangle]
crosvm_vcpu_get_regs( this: *mut crosvm_vcpu, regs: *mut kvm_regs, ) -> c_int1461 pub unsafe extern "C" fn crosvm_vcpu_get_regs(
1462 this: *mut crosvm_vcpu,
1463 regs: *mut kvm_regs,
1464 ) -> c_int {
1465 let _u = STATS.record(Stat::VcpuGetRegs);
1466 let this = &mut *this;
1467 let regs = from_raw_parts_mut(regs as *mut u8, size_of::<kvm_regs>());
1468 let ret = this.get_state(VcpuRequest_StateSet::REGS, regs);
1469 to_crosvm_rc(ret)
1470 }
1471
1472 #[no_mangle]
crosvm_vcpu_set_regs( this: *mut crosvm_vcpu, regs: *const kvm_regs, ) -> c_int1473 pub unsafe extern "C" fn crosvm_vcpu_set_regs(
1474 this: *mut crosvm_vcpu,
1475 regs: *const kvm_regs,
1476 ) -> c_int {
1477 let _u = STATS.record(Stat::VcpuSetRegs);
1478 let this = &mut *this;
1479 let regs = from_raw_parts(regs as *mut u8, size_of::<kvm_regs>());
1480 let ret = this.set_state(VcpuRequest_StateSet::REGS, regs);
1481 to_crosvm_rc(ret)
1482 }
1483
1484 #[no_mangle]
crosvm_vcpu_get_sregs( this: *mut crosvm_vcpu, sregs: *mut kvm_sregs, ) -> c_int1485 pub unsafe extern "C" fn crosvm_vcpu_get_sregs(
1486 this: *mut crosvm_vcpu,
1487 sregs: *mut kvm_sregs,
1488 ) -> c_int {
1489 let _u = STATS.record(Stat::VcpuGetSregs);
1490 let this = &mut *this;
1491 let sregs = from_raw_parts_mut(sregs as *mut u8, size_of::<kvm_sregs>());
1492 let ret = this.get_state(VcpuRequest_StateSet::SREGS, sregs);
1493 to_crosvm_rc(ret)
1494 }
1495
1496 #[no_mangle]
crosvm_vcpu_set_sregs( this: *mut crosvm_vcpu, sregs: *const kvm_sregs, ) -> c_int1497 pub unsafe extern "C" fn crosvm_vcpu_set_sregs(
1498 this: *mut crosvm_vcpu,
1499 sregs: *const kvm_sregs,
1500 ) -> c_int {
1501 let _u = STATS.record(Stat::VcpuSetSregs);
1502 let this = &mut *this;
1503 let sregs = from_raw_parts(sregs as *mut u8, size_of::<kvm_sregs>());
1504 let ret = this.set_state(VcpuRequest_StateSet::SREGS, sregs);
1505 to_crosvm_rc(ret)
1506 }
1507
1508 #[no_mangle]
crosvm_vcpu_get_fpu(this: *mut crosvm_vcpu, fpu: *mut kvm_fpu) -> c_int1509 pub unsafe extern "C" fn crosvm_vcpu_get_fpu(this: *mut crosvm_vcpu, fpu: *mut kvm_fpu) -> c_int {
1510 let _u = STATS.record(Stat::GetFpu);
1511 let this = &mut *this;
1512 let fpu = from_raw_parts_mut(fpu as *mut u8, size_of::<kvm_fpu>());
1513 let ret = this.get_state(VcpuRequest_StateSet::FPU, fpu);
1514 to_crosvm_rc(ret)
1515 }
1516
1517 #[no_mangle]
crosvm_vcpu_set_fpu(this: *mut crosvm_vcpu, fpu: *const kvm_fpu) -> c_int1518 pub unsafe extern "C" fn crosvm_vcpu_set_fpu(this: *mut crosvm_vcpu, fpu: *const kvm_fpu) -> c_int {
1519 let _u = STATS.record(Stat::SetFpu);
1520 let this = &mut *this;
1521 let fpu = from_raw_parts(fpu as *mut u8, size_of::<kvm_fpu>());
1522 let ret = this.set_state(VcpuRequest_StateSet::FPU, fpu);
1523 to_crosvm_rc(ret)
1524 }
1525
1526 #[no_mangle]
crosvm_vcpu_get_debugregs( this: *mut crosvm_vcpu, dregs: *mut kvm_debugregs, ) -> c_int1527 pub unsafe extern "C" fn crosvm_vcpu_get_debugregs(
1528 this: *mut crosvm_vcpu,
1529 dregs: *mut kvm_debugregs,
1530 ) -> c_int {
1531 let _u = STATS.record(Stat::GetDebugRegs);
1532 let this = &mut *this;
1533 let dregs = from_raw_parts_mut(dregs as *mut u8, size_of::<kvm_debugregs>());
1534 let ret = this.get_state(VcpuRequest_StateSet::DEBUGREGS, dregs);
1535 to_crosvm_rc(ret)
1536 }
1537
1538 #[no_mangle]
crosvm_vcpu_set_debugregs( this: *mut crosvm_vcpu, dregs: *const kvm_debugregs, ) -> c_int1539 pub unsafe extern "C" fn crosvm_vcpu_set_debugregs(
1540 this: *mut crosvm_vcpu,
1541 dregs: *const kvm_debugregs,
1542 ) -> c_int {
1543 let _u = STATS.record(Stat::SetDebugRegs);
1544 let this = &mut *this;
1545 let dregs = from_raw_parts(dregs as *mut u8, size_of::<kvm_debugregs>());
1546 let ret = this.set_state(VcpuRequest_StateSet::DEBUGREGS, dregs);
1547 to_crosvm_rc(ret)
1548 }
1549
1550 #[no_mangle]
crosvm_vcpu_get_xcrs( this: *mut crosvm_vcpu, xcrs: *mut kvm_xcrs, ) -> c_int1551 pub unsafe extern "C" fn crosvm_vcpu_get_xcrs(
1552 this: *mut crosvm_vcpu,
1553 xcrs: *mut kvm_xcrs,
1554 ) -> c_int {
1555 let _u = STATS.record(Stat::GetXCRegs);
1556 let this = &mut *this;
1557 let xcrs = from_raw_parts_mut(xcrs as *mut u8, size_of::<kvm_xcrs>());
1558 let ret = this.get_state(VcpuRequest_StateSet::XCREGS, xcrs);
1559 to_crosvm_rc(ret)
1560 }
1561
1562 #[no_mangle]
crosvm_vcpu_set_xcrs( this: *mut crosvm_vcpu, xcrs: *const kvm_xcrs, ) -> c_int1563 pub unsafe extern "C" fn crosvm_vcpu_set_xcrs(
1564 this: *mut crosvm_vcpu,
1565 xcrs: *const kvm_xcrs,
1566 ) -> c_int {
1567 let _u = STATS.record(Stat::SetXCRegs);
1568 let this = &mut *this;
1569 let xcrs = from_raw_parts(xcrs as *mut u8, size_of::<kvm_xcrs>());
1570 let ret = this.set_state(VcpuRequest_StateSet::XCREGS, xcrs);
1571 to_crosvm_rc(ret)
1572 }
1573
1574 #[no_mangle]
crosvm_vcpu_get_msrs( this: *mut crosvm_vcpu, msr_count: u32, msr_entries: *mut kvm_msr_entry, out_count: *mut u32, ) -> c_int1575 pub unsafe extern "C" fn crosvm_vcpu_get_msrs(
1576 this: *mut crosvm_vcpu,
1577 msr_count: u32,
1578 msr_entries: *mut kvm_msr_entry,
1579 out_count: *mut u32,
1580 ) -> c_int {
1581 let _u = STATS.record(Stat::VcpuGetMsrs);
1582 let this = &mut *this;
1583 let msr_entries = from_raw_parts_mut(msr_entries, msr_count as usize);
1584 let mut count: usize = 0;
1585 let ret = this.get_msrs(msr_entries, &mut count);
1586 *out_count = count as u32;
1587 to_crosvm_rc(ret)
1588 }
1589
1590 #[no_mangle]
crosvm_vcpu_set_msrs( this: *mut crosvm_vcpu, msr_count: u32, msr_entries: *const kvm_msr_entry, ) -> c_int1591 pub unsafe extern "C" fn crosvm_vcpu_set_msrs(
1592 this: *mut crosvm_vcpu,
1593 msr_count: u32,
1594 msr_entries: *const kvm_msr_entry,
1595 ) -> c_int {
1596 let _u = STATS.record(Stat::VcpuSetMsrs);
1597 let this = &mut *this;
1598 let msr_entries = from_raw_parts(msr_entries, msr_count as usize);
1599 let ret = this.set_msrs(msr_entries);
1600 to_crosvm_rc(ret)
1601 }
1602
1603 #[no_mangle]
crosvm_vcpu_set_cpuid( this: *mut crosvm_vcpu, cpuid_count: u32, cpuid_entries: *const kvm_cpuid_entry2, ) -> c_int1604 pub unsafe extern "C" fn crosvm_vcpu_set_cpuid(
1605 this: *mut crosvm_vcpu,
1606 cpuid_count: u32,
1607 cpuid_entries: *const kvm_cpuid_entry2,
1608 ) -> c_int {
1609 let _u = STATS.record(Stat::VcpuSetCpuid);
1610 let this = &mut *this;
1611 let cpuid_entries = from_raw_parts(cpuid_entries, cpuid_count as usize);
1612 let ret = this.set_cpuid(cpuid_entries);
1613 to_crosvm_rc(ret)
1614 }
1615
1616 #[no_mangle]
crosvm_vcpu_get_lapic_state( this: *mut crosvm_vcpu, state: *mut kvm_lapic_state, ) -> c_int1617 pub unsafe extern "C" fn crosvm_vcpu_get_lapic_state(
1618 this: *mut crosvm_vcpu,
1619 state: *mut kvm_lapic_state,
1620 ) -> c_int {
1621 let _u = STATS.record(Stat::VcpuGetLapicState);
1622 let this = &mut *this;
1623 let state = from_raw_parts_mut(state as *mut u8, size_of::<kvm_lapic_state>());
1624 let ret = this.get_state(VcpuRequest_StateSet::LAPIC, state);
1625 to_crosvm_rc(ret)
1626 }
1627
1628 #[no_mangle]
crosvm_vcpu_set_lapic_state( this: *mut crosvm_vcpu, state: *const kvm_lapic_state, ) -> c_int1629 pub unsafe extern "C" fn crosvm_vcpu_set_lapic_state(
1630 this: *mut crosvm_vcpu,
1631 state: *const kvm_lapic_state,
1632 ) -> c_int {
1633 let _u = STATS.record(Stat::VcpuSetLapicState);
1634 let this = &mut *this;
1635 let state = from_raw_parts(state as *mut u8, size_of::<kvm_lapic_state>());
1636 let ret = this.set_state(VcpuRequest_StateSet::LAPIC, state);
1637 to_crosvm_rc(ret)
1638 }
1639
1640 #[no_mangle]
crosvm_vcpu_get_mp_state( this: *mut crosvm_vcpu, state: *mut kvm_mp_state, ) -> c_int1641 pub unsafe extern "C" fn crosvm_vcpu_get_mp_state(
1642 this: *mut crosvm_vcpu,
1643 state: *mut kvm_mp_state,
1644 ) -> c_int {
1645 let _u = STATS.record(Stat::VcpuGetMpState);
1646 let this = &mut *this;
1647 let state = from_raw_parts_mut(state as *mut u8, size_of::<kvm_mp_state>());
1648 let ret = this.get_state(VcpuRequest_StateSet::MP, state);
1649 to_crosvm_rc(ret)
1650 }
1651
1652 #[no_mangle]
crosvm_vcpu_set_mp_state( this: *mut crosvm_vcpu, state: *const kvm_mp_state, ) -> c_int1653 pub unsafe extern "C" fn crosvm_vcpu_set_mp_state(
1654 this: *mut crosvm_vcpu,
1655 state: *const kvm_mp_state,
1656 ) -> c_int {
1657 let _u = STATS.record(Stat::VcpuSetMpState);
1658 let this = &mut *this;
1659 let state = from_raw_parts(state as *mut u8, size_of::<kvm_mp_state>());
1660 let ret = this.set_state(VcpuRequest_StateSet::MP, state);
1661 to_crosvm_rc(ret)
1662 }
1663
1664 #[no_mangle]
crosvm_vcpu_get_vcpu_events( this: *mut crosvm_vcpu, events: *mut kvm_vcpu_events, ) -> c_int1665 pub unsafe extern "C" fn crosvm_vcpu_get_vcpu_events(
1666 this: *mut crosvm_vcpu,
1667 events: *mut kvm_vcpu_events,
1668 ) -> c_int {
1669 let _u = STATS.record(Stat::VcpuGetVcpuEvents);
1670 let this = &mut *this;
1671 let events = from_raw_parts_mut(events as *mut u8, size_of::<kvm_vcpu_events>());
1672 let ret = this.get_state(VcpuRequest_StateSet::EVENTS, events);
1673 to_crosvm_rc(ret)
1674 }
1675
1676 #[no_mangle]
crosvm_vcpu_set_vcpu_events( this: *mut crosvm_vcpu, events: *const kvm_vcpu_events, ) -> c_int1677 pub unsafe extern "C" fn crosvm_vcpu_set_vcpu_events(
1678 this: *mut crosvm_vcpu,
1679 events: *const kvm_vcpu_events,
1680 ) -> c_int {
1681 let _u = STATS.record(Stat::VcpuSetVcpuEvents);
1682 let this = &mut *this;
1683 let events = from_raw_parts(events as *mut u8, size_of::<kvm_vcpu_events>());
1684 let ret = this.set_state(VcpuRequest_StateSet::EVENTS, events);
1685 to_crosvm_rc(ret)
1686 }
1687