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