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