kvm_sys/
lib.rs

1// Copyright 2015 Dan Schatzberg.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Rust API to Kernel-based Virtual Machine (KVM)
16#![deny(missing_docs,
17        missing_debug_implementations, missing_copy_implementations,
18        trivial_casts, trivial_numeric_casts,
19        unstable_features,
20        unused_import_braces, unused_qualifications)]
21
22#![cfg_attr(feature = "dev", allow(unstable_features))]
23#![cfg_attr(feature = "dev", feature(plugin))]
24#![cfg_attr(feature = "dev", plugin(clippy))]
25
26extern crate errno;
27extern crate libc;
28#[macro_use]
29extern crate log;
30extern crate memmap;
31
32#[cfg(target_arch = "x86_64")]
33#[allow(missing_docs, missing_debug_implementations)]
34mod x86_64;
35
36#[cfg(target_arch = "x86_64")]
37pub use self::x86_64::*;
38
39use errno::{Errno, errno};
40use libc::{E2BIG, ENOMEM, c_int};
41use std::fmt;
42use std::fs::{File, OpenOptions};
43use std::io::{self, Error, ErrorKind};
44use std::mem;
45use std::ops::DerefMut;
46use std::os::unix::io::{AsRawFd, FromRawFd};
47
48use memmap::{Mmap, Protection};
49
50const API_VERSION: i32 = 12;
51
52extern {
53    fn kvm_get_api_version(fd: c_int) -> c_int;
54    fn kvm_create_vm(fd: c_int, flags: c_int) -> c_int;
55    fn kvm_check_extension(fd: c_int, extension: c_int) -> c_int;
56    fn kvm_get_vcpu_mmap_size(fd: c_int) -> c_int;
57    fn kvm_get_supported_cpuid(fd: c_int, cpuid: *mut Cpuid2) -> c_int;
58    fn kvm_create_vcpu(fd: c_int, vcpu_id: c_int) -> c_int;
59    fn kvm_set_user_memory_region(fd: c_int,
60                                  region: *const UserspaceMemoryRegion)
61                                  -> c_int;
62    fn kvm_run(fd: c_int) -> c_int;
63    fn kvm_get_regs(fd: c_int, regs: *mut Regs) -> c_int;
64    fn kvm_set_regs(fd: c_int, regs: *const Regs) -> c_int;
65    fn kvm_get_sregs(fd: c_int, sregs: *mut Sregs) -> c_int;
66    fn kvm_set_sregs(fd: c_int, sregs: *const Sregs) -> c_int;
67    fn kvm_set_cpuid2(fd: c_int, cpuid: *const Cpuid2) -> c_int;
68}
69
70/// Handle to the KVM system.
71///
72/// This is used to create virtual machines and query the system for
73/// its capabilities.
74#[derive(Debug)]
75pub struct System {
76    fd: File,
77}
78
79/// A Virtual Machine.
80///
81/// This allows the creation of `Vcpu`s and establishing memory mappings
82#[derive(Debug)]
83pub struct VirtualMachine<'a> {
84    fd: File,
85    sys: &'a System,
86    mem_slots: Vec<&'a mut [u8]>,
87    num_vcpus: u32,
88    check_extension: bool,
89}
90
91/// Result type used by this crate
92pub type Result<T> = io::Result<T>;
93
94/// KVM system capabilities
95#[allow(missing_docs)]
96#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
97#[repr(i32)]
98pub enum Capability {
99    Irqchip,
100    Hlt,
101    MmuShadowCacheControl,
102    UserMemory,
103    SetTssAddr,
104    Vapic = 6,
105    ExtCpuid,
106    ClockSource,
107    NrVcpus,
108    NrMemSlots,
109    Pit,
110    NopIoDelay,
111    PvMmu,
112    MpState,
113    CoalescedMmio,
114    SyncMmu,
115    IoMmu = 18,
116    DestroyMemoryRegionWorks = 21,
117    UserNmi,
118    MaxVcpus = 66,
119    CheckExtensionVm = 105,
120}
121
122/// KVM `run` exit reasons
123#[allow(missing_docs)]
124#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
125#[repr(u32)]
126pub enum Exit {
127    Unknown,
128    Exception,
129    Io,
130    Hypercall,
131    Debug,
132    Hlt,
133    Mmio,
134    IrqWindowOpen,
135    Shutdown,
136    FailEntry,
137    Intr,
138    SetTpr,
139    TprAccess,
140    S390Sieic,
141    S390Reset,
142    Dcr,
143    Nmi,
144    InternalError,
145    Osi,
146    PaprHcall,
147    S390Ucontrol,
148    Watchdog,
149    S390Tsch,
150    Epr,
151    SystemEvent,
152}
153
154#[repr(C)]
155#[derive(Clone, Copy, Debug, Default)]
156struct UserspaceMemoryRegion {
157    pub slot: u32,
158    pub flags: u32,
159    pub guest_phys_addr: u64,
160    pub memory_size: u64,
161    pub userspace_addr: u64,
162}
163
164/// A Virtual CPU.
165pub struct Vcpu<'a> {
166    fd: File,
167    vm: &'a VirtualMachine<'a>,
168    mmap: Mmap,
169}
170
171impl<'a> fmt::Debug for Vcpu<'a> {
172    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
173        fmt.debug_struct("Vcpu")
174           .field("fd", &self.fd)
175           .field("vm", &self.vm)
176           .finish()
177    }
178}
179
180
181/// Information about the reason `run` returned
182#[allow(missing_docs)]
183#[repr(C)]
184#[derive(Copy)]
185pub struct Run {
186    request_interrupt_window: u8,
187    padding1: [u8; 7usize],
188    pub exit_reason: Exit,
189    pub ready_for_interrupt_injection: u8,
190    pub if_flag: u8,
191    pub flags: u16,
192    pub cr8: u64,
193    pub apic_base: u64,
194    _bindgen_data_1_: [u64; 32usize],
195    pub kvm_valid_regs: u64,
196    pub kvm_dirty_regs: u64,
197    pub s: Union_Unnamed26,
198}
199
200#[allow(missing_docs)]
201impl Run {
202    pub fn hw(&self) -> *const Struct_Unnamed9 {
203        unsafe {
204            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
205            ::std::mem::transmute(raw.offset(0))
206        }
207    }
208    pub fn hw_mut(&mut self) -> *mut Struct_Unnamed9 {
209        unsafe {
210            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
211            ::std::mem::transmute(raw.offset(0))
212        }
213    }
214    pub fn fail_entry(&self) -> *const Struct_Unnamed10 {
215        unsafe {
216            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
217            ::std::mem::transmute(raw.offset(0))
218        }
219    }
220    pub fn fail_entry_mut(&mut self) -> *mut Struct_Unnamed10 {
221        unsafe {
222            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
223            ::std::mem::transmute(raw.offset(0))
224        }
225    }
226    pub fn ex(&self) -> *const Struct_Unnamed11 {
227        unsafe {
228            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
229            ::std::mem::transmute(raw.offset(0))
230        }
231    }
232    pub fn ex_mut(&mut self) -> *mut Struct_Unnamed11 {
233        unsafe {
234            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
235            ::std::mem::transmute(raw.offset(0))
236        }
237    }
238    pub fn io(&self) -> *const ExitIo {
239        unsafe {
240            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
241            ::std::mem::transmute(raw.offset(0))
242        }
243    }
244    pub fn io_mut(&mut self) -> *mut ExitIo {
245        unsafe {
246            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
247            ::std::mem::transmute(raw.offset(0))
248        }
249    }
250    pub fn debug(&self) -> *const Struct_Unnamed13 {
251        unsafe {
252            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
253            ::std::mem::transmute(raw.offset(0))
254        }
255    }
256    pub fn debug_mut(&mut self) -> *mut Struct_Unnamed13 {
257        unsafe {
258            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
259            ::std::mem::transmute(raw.offset(0))
260        }
261    }
262    pub fn mmio(&self) -> *const Struct_Unnamed14 {
263        unsafe {
264            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
265            ::std::mem::transmute(raw.offset(0))
266        }
267    }
268    pub fn mmio_mut(&mut self) -> *mut Struct_Unnamed14 {
269        unsafe {
270            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
271            ::std::mem::transmute(raw.offset(0))
272        }
273    }
274    pub fn hypercall(&self) -> *const Struct_Unnamed15 {
275        unsafe {
276            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
277            ::std::mem::transmute(raw.offset(0))
278        }
279    }
280    pub fn hypercall_mut(&mut self) -> *mut Struct_Unnamed15 {
281        unsafe {
282            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
283            ::std::mem::transmute(raw.offset(0))
284        }
285    }
286    pub fn tpr_access(&self) -> *const Struct_Unnamed16 {
287        unsafe {
288            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
289            ::std::mem::transmute(raw.offset(0))
290        }
291    }
292    pub fn tpr_access_mut(&mut self) -> *mut Struct_Unnamed16 {
293        unsafe {
294            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
295            ::std::mem::transmute(raw.offset(0))
296        }
297    }
298    pub fn s390_sieic(&self) -> *const Struct_Unnamed17 {
299        unsafe {
300            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
301            ::std::mem::transmute(raw.offset(0))
302        }
303    }
304    pub fn s390_sieic_mut(&mut self) -> *mut Struct_Unnamed17 {
305        unsafe {
306            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
307            ::std::mem::transmute(raw.offset(0))
308        }
309    }
310    pub fn s390_reset_flags(&self) -> *const u64 {
311        unsafe {
312            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
313            ::std::mem::transmute(raw.offset(0))
314        }
315    }
316    pub fn s390_reset_flags_mut(&mut self) -> *mut u64 {
317        unsafe {
318            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
319            ::std::mem::transmute(raw.offset(0))
320        }
321    }
322    pub fn s390_ucontrol(&self) -> *const Struct_Unnamed18 {
323        unsafe {
324            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
325            ::std::mem::transmute(raw.offset(0))
326        }
327    }
328    pub fn s390_ucontrol_mut(&mut self) -> *mut Struct_Unnamed18 {
329        unsafe {
330            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
331            ::std::mem::transmute(raw.offset(0))
332        }
333    }
334    pub fn dcr(&self) -> *const Struct_Unnamed19 {
335        unsafe {
336            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
337            ::std::mem::transmute(raw.offset(0))
338        }
339    }
340    pub fn dcr_mut(&mut self) -> *mut Struct_Unnamed19 {
341        unsafe {
342            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
343            ::std::mem::transmute(raw.offset(0))
344        }
345    }
346    pub fn internal(&self) -> *const Struct_Unnamed20 {
347        unsafe {
348            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
349            ::std::mem::transmute(raw.offset(0))
350        }
351    }
352    pub fn internal_mut(&mut self) -> *mut Struct_Unnamed20 {
353        unsafe {
354            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
355            ::std::mem::transmute(raw.offset(0))
356        }
357    }
358    pub fn osi(&self) -> *const Struct_Unnamed21 {
359        unsafe {
360            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
361            ::std::mem::transmute(raw.offset(0))
362        }
363    }
364    pub fn osi_mut(&mut self) -> *mut Struct_Unnamed21 {
365        unsafe {
366            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
367            ::std::mem::transmute(raw.offset(0))
368        }
369    }
370    pub fn papr_hcall(&self) -> *const Struct_Unnamed22 {
371        unsafe {
372            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
373            ::std::mem::transmute(raw.offset(0))
374        }
375    }
376    pub fn papr_hcall_mut(&mut self) -> *mut Struct_Unnamed22 {
377        unsafe {
378            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
379            ::std::mem::transmute(raw.offset(0))
380        }
381    }
382    pub fn s390_tsch(&self) -> *const Struct_Unnamed23 {
383        unsafe {
384            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
385            ::std::mem::transmute(raw.offset(0))
386        }
387    }
388    pub fn s390_tsch_mut(&mut self) -> *mut Struct_Unnamed23 {
389        unsafe {
390            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
391            ::std::mem::transmute(raw.offset(0))
392        }
393    }
394    pub fn epr(&self) -> *const Struct_Unnamed24 {
395        unsafe {
396            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
397            ::std::mem::transmute(raw.offset(0))
398        }
399    }
400    pub fn epr_mut(&mut self) -> *mut Struct_Unnamed24 {
401        unsafe {
402            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
403            ::std::mem::transmute(raw.offset(0))
404        }
405    }
406    pub fn system_event(&self) -> *const Struct_Unnamed25 {
407        unsafe {
408            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
409            ::std::mem::transmute(raw.offset(0))
410        }
411    }
412    pub fn system_event_mut(&mut self) -> *mut Struct_Unnamed25 {
413        unsafe {
414            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_1_);
415            ::std::mem::transmute(raw.offset(0))
416        }
417    }
418}
419impl ::std::clone::Clone for Run {
420    fn clone(&self) -> Self {
421        *self
422    }
423}
424impl ::std::default::Default for Run {
425    fn default() -> Self {
426        unsafe { ::std::mem::zeroed() }
427    }
428}
429
430impl fmt::Debug for Run {
431    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
432        let mut s = fmt.debug_struct("Run");
433        s.field("request_interrupt_window", &self.request_interrupt_window)
434         .field("exit_reason", &self.exit_reason)
435         .field("ready_for_interrupt_injection",
436                &self.ready_for_interrupt_injection)
437         .field("if_flag", &self.if_flag)
438         .field("flags", &self.flags)
439         .field("cr8", &self.cr8);
440        unsafe {
441            match self.exit_reason {
442                Exit::Unknown => s.field("hw", &*self.hw()),
443                Exit::FailEntry => s.field("fail_entry", &*self.fail_entry()),
444                Exit::Exception => s.field("ex", &*self.ex()),
445                Exit::Io => s.field("io", &*self.io()),
446                Exit::Debug => s.field("debug", &*self.debug()),
447                Exit::Mmio => s.field("mmio", &*self.mmio()),
448                Exit::Hypercall => s.field("hypercall", &*self.hypercall()),
449                Exit::TprAccess => s.field("tpr_access", &*self.tpr_access()),
450                Exit::S390Sieic => s.field("s390_sieic", &*self.s390_sieic()),
451                Exit::S390Reset =>
452                    s.field("s390_reset_flags", &*self.s390_reset_flags()),
453                Exit::S390Ucontrol =>
454                    s.field("s390_ucontrol", &*self.s390_ucontrol()),
455                Exit::Dcr => s.field("dcr", &*self.dcr()),
456                Exit::Osi => s.field("osi", &*self.osi()),
457                Exit::PaprHcall => s.field("papr_hcall", &*self.papr_hcall()),
458                Exit::S390Tsch => s.field("s390_tsch", &*self.s390_tsch()),
459                Exit::Epr => s.field("epr", &*self.epr()),
460                Exit::SystemEvent =>
461                    s.field("system_event", &*self.system_event()),
462                _ => &mut s,
463            }
464        }
465        .finish()
466    }
467}
468#[allow(missing_docs)]
469#[repr(C)]
470#[derive(Copy, Debug)]
471pub struct Struct_Unnamed9 {
472    pub hardware_exit_reason: u64,
473}
474impl ::std::clone::Clone for Struct_Unnamed9 {
475    fn clone(&self) -> Self {
476        *self
477    }
478}
479impl ::std::default::Default for Struct_Unnamed9 {
480    fn default() -> Self {
481        unsafe { ::std::mem::zeroed() }
482    }
483}
484#[allow(missing_docs)]
485#[repr(C)]
486#[derive(Copy, Debug)]
487pub struct Struct_Unnamed10 {
488    pub hardware_entry_failure_reason: u64,
489}
490impl ::std::clone::Clone for Struct_Unnamed10 {
491    fn clone(&self) -> Self {
492        *self
493    }
494}
495impl ::std::default::Default for Struct_Unnamed10 {
496    fn default() -> Self {
497        unsafe { ::std::mem::zeroed() }
498    }
499}
500#[allow(missing_docs)]
501#[repr(C)]
502#[derive(Copy, Debug)]
503pub struct Struct_Unnamed11 {
504    pub exception: u32,
505    pub error_code: u32,
506}
507impl ::std::clone::Clone for Struct_Unnamed11 {
508    fn clone(&self) -> Self {
509        *self
510    }
511}
512impl ::std::default::Default for Struct_Unnamed11 {
513    fn default() -> Self {
514        unsafe { ::std::mem::zeroed() }
515    }
516}
517
518#[allow(missing_docs)]
519#[repr(u8)]
520#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
521pub enum IoDirection {
522    In,
523    Out,
524}
525
526#[allow(missing_docs)]
527#[repr(C)]
528#[derive(Copy, Debug)]
529pub struct ExitIo {
530    pub direction: IoDirection,
531    pub size: u8,
532    pub port: u16,
533    pub count: u32,
534    pub data_offset: u64,
535}
536impl ::std::clone::Clone for ExitIo {
537    fn clone(&self) -> Self {
538        *self
539    }
540}
541impl ::std::default::Default for ExitIo {
542    fn default() -> Self {
543        unsafe { ::std::mem::zeroed() }
544    }
545}
546#[allow(missing_docs)]
547#[repr(C)]
548#[derive(Copy, Debug)]
549pub struct Struct_Unnamed13 {
550    pub arch: DebugExitArch,
551}
552impl ::std::clone::Clone for Struct_Unnamed13 {
553    fn clone(&self) -> Self {
554        *self
555    }
556}
557impl ::std::default::Default for Struct_Unnamed13 {
558    fn default() -> Self {
559        unsafe { ::std::mem::zeroed() }
560    }
561}
562#[allow(missing_docs)]
563#[repr(C)]
564#[derive(Copy, Debug)]
565pub struct Struct_Unnamed14 {
566    pub phys_addr: u64,
567    pub data: [u8; 8usize],
568    pub len: u32,
569    pub is_write: u8,
570}
571impl ::std::clone::Clone for Struct_Unnamed14 {
572    fn clone(&self) -> Self {
573        *self
574    }
575}
576impl ::std::default::Default for Struct_Unnamed14 {
577    fn default() -> Self {
578        unsafe { ::std::mem::zeroed() }
579    }
580}
581#[allow(missing_docs)]
582#[repr(C)]
583#[derive(Copy, Debug)]
584pub struct Struct_Unnamed15 {
585    pub nr: u64,
586    pub args: [u64; 6usize],
587    pub ret: u64,
588    pub longmode: u32,
589    pub pad: u32,
590}
591impl ::std::clone::Clone for Struct_Unnamed15 {
592    fn clone(&self) -> Self {
593        *self
594    }
595}
596impl ::std::default::Default for Struct_Unnamed15 {
597    fn default() -> Self {
598        unsafe { ::std::mem::zeroed() }
599    }
600}
601#[allow(missing_docs)]
602#[repr(C)]
603#[derive(Copy, Debug)]
604pub struct Struct_Unnamed16 {
605    pub rip: u64,
606    pub is_write: u32,
607    pub pad: u32,
608}
609impl ::std::clone::Clone for Struct_Unnamed16 {
610    fn clone(&self) -> Self {
611        *self
612    }
613}
614impl ::std::default::Default for Struct_Unnamed16 {
615    fn default() -> Self {
616        unsafe { ::std::mem::zeroed() }
617    }
618}
619#[allow(missing_docs)]
620#[repr(C)]
621#[derive(Copy, Debug)]
622pub struct Struct_Unnamed17 {
623    pub icptcode: u8,
624    pub ipa: u16,
625    pub ipb: u32,
626}
627impl ::std::clone::Clone for Struct_Unnamed17 {
628    fn clone(&self) -> Self {
629        *self
630    }
631}
632impl ::std::default::Default for Struct_Unnamed17 {
633    fn default() -> Self {
634        unsafe { ::std::mem::zeroed() }
635    }
636}
637#[allow(missing_docs)]
638#[repr(C)]
639#[derive(Copy, Debug)]
640pub struct Struct_Unnamed18 {
641    pub trans_exc_code: u64,
642    pub pgm_code: u32,
643}
644impl ::std::clone::Clone for Struct_Unnamed18 {
645    fn clone(&self) -> Self {
646        *self
647    }
648}
649impl ::std::default::Default for Struct_Unnamed18 {
650    fn default() -> Self {
651        unsafe { ::std::mem::zeroed() }
652    }
653}
654#[allow(missing_docs)]
655#[repr(C)]
656#[derive(Copy, Debug)]
657pub struct Struct_Unnamed19 {
658    pub dcrn: u32,
659    pub data: u32,
660    pub is_write: u8,
661}
662impl ::std::clone::Clone for Struct_Unnamed19 {
663    fn clone(&self) -> Self {
664        *self
665    }
666}
667impl ::std::default::Default for Struct_Unnamed19 {
668    fn default() -> Self {
669        unsafe { ::std::mem::zeroed() }
670    }
671}
672#[allow(missing_docs)]
673#[repr(C)]
674#[derive(Copy, Debug)]
675pub struct Struct_Unnamed20 {
676    pub suberror: u32,
677    pub ndata: u32,
678    pub data: [u64; 16usize],
679}
680impl ::std::clone::Clone for Struct_Unnamed20 {
681    fn clone(&self) -> Self {
682        *self
683    }
684}
685impl ::std::default::Default for Struct_Unnamed20 {
686    fn default() -> Self {
687        unsafe { ::std::mem::zeroed() }
688    }
689}
690#[allow(missing_docs)]
691#[repr(C)]
692#[derive(Copy, Debug)]
693pub struct Struct_Unnamed21 {
694    pub gprs: [u64; 32usize],
695}
696impl ::std::clone::Clone for Struct_Unnamed21 {
697    fn clone(&self) -> Self {
698        *self
699    }
700}
701impl ::std::default::Default for Struct_Unnamed21 {
702    fn default() -> Self {
703        unsafe { ::std::mem::zeroed() }
704    }
705}
706#[allow(missing_docs)]
707#[repr(C)]
708#[derive(Copy, Debug)]
709pub struct Struct_Unnamed22 {
710    pub nr: u64,
711    pub ret: u64,
712    pub args: [u64; 9usize],
713}
714impl ::std::clone::Clone for Struct_Unnamed22 {
715    fn clone(&self) -> Self {
716        *self
717    }
718}
719impl ::std::default::Default for Struct_Unnamed22 {
720    fn default() -> Self {
721        unsafe { ::std::mem::zeroed() }
722    }
723}
724#[allow(missing_docs)]
725#[repr(C)]
726#[derive(Copy, Debug)]
727pub struct Struct_Unnamed23 {
728    pub subchannel_id: u16,
729    pub subchannel_nr: u16,
730    pub io_int_parm: u32,
731    pub io_int_word: u32,
732    pub ipb: u32,
733    pub dequeued: u8,
734}
735impl ::std::clone::Clone for Struct_Unnamed23 {
736    fn clone(&self) -> Self {
737        *self
738    }
739}
740impl ::std::default::Default for Struct_Unnamed23 {
741    fn default() -> Self {
742        unsafe { ::std::mem::zeroed() }
743    }
744}
745#[allow(missing_docs)]
746#[repr(C)]
747#[derive(Copy, Debug)]
748pub struct Struct_Unnamed24 {
749    pub epr: u32,
750}
751impl ::std::clone::Clone for Struct_Unnamed24 {
752    fn clone(&self) -> Self {
753        *self
754    }
755}
756impl ::std::default::Default for Struct_Unnamed24 {
757    fn default() -> Self {
758        unsafe { ::std::mem::zeroed() }
759    }
760}
761#[allow(missing_docs)]
762#[repr(C)]
763#[derive(Copy, Debug)]
764pub struct Struct_Unnamed25 {
765    pub _type: u32,
766    pub flags: u64,
767}
768impl ::std::clone::Clone for Struct_Unnamed25 {
769    fn clone(&self) -> Self {
770        *self
771    }
772}
773impl ::std::default::Default for Struct_Unnamed25 {
774    fn default() -> Self {
775        unsafe { ::std::mem::zeroed() }
776    }
777}
778#[allow(missing_docs, missing_debug_implementations)]
779#[repr(C)]
780#[derive(Copy)]
781pub struct Union_Unnamed26 {
782    pub _bindgen_data_: [u8; 1024usize],
783}
784#[allow(missing_docs)]
785impl Union_Unnamed26 {
786    pub fn regs(&self) -> *const SyncRegs {
787        unsafe {
788            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
789            ::std::mem::transmute(raw.offset(0))
790        }
791    }
792    pub fn regs_mut(&mut self) -> *mut SyncRegs {
793        unsafe {
794            let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
795            ::std::mem::transmute(raw.offset(0))
796        }
797    }
798}
799impl ::std::clone::Clone for Union_Unnamed26 {
800    fn clone(&self) -> Self {
801        *self
802    }
803}
804impl ::std::default::Default for Union_Unnamed26 {
805    fn default() -> Self {
806        unsafe { ::std::mem::zeroed() }
807    }
808}
809
810impl System {
811    /// Initialize the KVM system
812    pub fn initialize() -> Result<Self> {
813        let f = try!(OpenOptions::new()
814                         .read(true)
815                         .write(true)
816                         .open("/dev/kvm"));
817        let vers = unsafe { kvm_get_api_version(f.as_raw_fd()) };
818        if vers == API_VERSION {
819            Ok(System { fd: f })
820        } else {
821            Err(Error::new(ErrorKind::NotFound, "Unexpected API Version"))
822        }
823    }
824
825    /// Check for the existence of a capability.
826    ///
827    /// Where possible use the associated function on a `VirtualMachine` rather
828    /// than the `System` since `VirtualMachine`s may have different
829    /// capabilities
830    pub fn check_capability(&self, cap: Capability) -> i32 {
831        unsafe { kvm_check_extension(self.fd.as_raw_fd(), cap as c_int) }
832    }
833
834    /// Recommended maximum number of `Vcpu`s
835    pub fn recommended_vcpus(&self) -> u32 {
836        let r = self.check_capability(Capability::NrVcpus);
837        if r != 0 {
838            r as u32
839        } else {
840            // From api.txt: If the KVM_CAP_NR_VCPUS does not exist, you should
841            // assume that max_vcpus is 4 cpus max.
842            4
843        }
844    }
845
846    /// Maximum number of `Vcpu`s
847    pub fn max_vcpus(&self) -> u32 {
848        let r = self.check_capability(Capability::MaxVcpus);
849        if r != 0 {
850            r as u32
851        } else {
852            self.recommended_vcpus()
853        }
854    }
855
856    fn get_vcpu_mmap_size(&self) -> usize {
857        let ret = unsafe { kvm_get_vcpu_mmap_size(self.fd.as_raw_fd()) };
858        assert!(ret > 0 && ret as usize >= mem::size_of::<Run>());
859        ret as usize
860    }
861}
862
863#[cfg(target_arch = "x86_64")]
864const CPUID_ENTRIES: u32 = 64;
865
866#[cfg(target_arch = "x86_64")]
867impl System {
868    /// Get CPUID features supported by this host
869    pub fn get_supported_cpuid(&self) -> Result<CpuidHandle> {
870        let mut nent = CPUID_ENTRIES;
871        loop {
872            let mut c = CpuidHandle::new(nent);
873            let err = unsafe {
874                kvm_get_supported_cpuid(self.fd.as_raw_fd(), c.deref_mut())
875            };
876            if err != 0 {
877                if errno() == Errno(E2BIG) {
878                    nent *= 2;
879                    continue;
880                } else if errno() == Errno(ENOMEM) {
881                    nent = c.nent;
882                    continue;
883                } else {
884                    return Err(Error::last_os_error());
885                }
886            } else {
887                return Ok(c);
888            }
889        }
890    }
891}
892
893/// Instruct KVM to keep track of writes to memory within the slot
894pub const MEM_LOG_DIRTY_PAGES: u32 = 1;
895/// If `Capability::ReadonlyMem`, make this mapping read-only
896pub const MEM_READONLY: u32 = 1 << 1;
897
898impl<'a> VirtualMachine<'a> {
899    /// Create a `VirtualMachine`
900    pub fn create(s: &'a System) -> Result<Self> {
901        let f = unsafe { kvm_create_vm(s.fd.as_raw_fd(), 0) };
902        if f == -1 {
903            return Err(Error::last_os_error());
904        }
905
906        let check_extension =
907            s.check_capability(Capability::CheckExtensionVm) != 0;
908        Ok(VirtualMachine {
909            fd: unsafe { File::from_raw_fd(f) },
910            sys: s,
911            mem_slots: Vec::new(),
912            num_vcpus: 0,
913            check_extension: check_extension,
914        })
915    }
916
917    /// Check for a capability on this `VirtualMachine`
918    pub fn check_capability(&mut self, cap: Capability) -> i32 {
919        if self.check_extension {
920            unsafe { kvm_check_extension(self.fd.as_raw_fd(), cap as c_int) }
921        } else {
922            self.sys.check_capability(cap)
923        }
924    }
925
926    /// Establish a guest memory mapping.
927    ///
928    /// The slice specified by `user_addr` is mapped at `phys_addr`. Flags is
929    /// the bitwise or of `MEM_LOG_DIRTY_PAGES` and/or `MEM_READONLY`.
930    pub fn set_user_memory_region(&mut self,
931                                  phys_addr: u64,
932                                  user_addr: &'a mut [u8],
933                                  flags: u32)
934                                  -> Result<()> {
935        let slot = self.mem_slots.len();
936        let region = UserspaceMemoryRegion {
937            slot: slot as u32,
938            flags: flags,
939            guest_phys_addr: phys_addr,
940            memory_size: user_addr.len() as u64,
941            userspace_addr: user_addr.as_mut_ptr() as u64,
942        };
943        let ret = unsafe {
944            kvm_set_user_memory_region(self.fd.as_raw_fd(), &region)
945        };
946        if ret == 0 {
947            self.mem_slots.push(user_addr);
948            Ok(())
949        } else {
950            Err(Error::new(ErrorKind::Other, "Unknown Error"))
951        }
952    }
953}
954
955impl<'a> Vcpu<'a> {
956    /// Create a `Vcpu` on the specified `VirtualMachine`
957    pub fn create(vm: &'a mut VirtualMachine<'a>) -> Result<Self> {
958        if vm.num_vcpus >= vm.sys.max_vcpus() {
959            return Err(Error::new(ErrorKind::AlreadyExists,
960                                  "Would exceed max_vcpus"));
961        } else if vm.num_vcpus >= vm.sys.recommended_vcpus() {
962            warn!("Exceeding recommended_vcpus");
963        }
964        let fd = unsafe {
965            File::from_raw_fd(kvm_create_vcpu(vm.fd.as_raw_fd(),
966                                              vm.num_vcpus as c_int))
967        };
968        vm.num_vcpus += 1;
969        let mmap_size = vm.sys.get_vcpu_mmap_size();
970        let m = try!(Mmap::open_with_offset(&fd,
971                                            Protection::ReadWrite,
972                                            0,
973                                            mmap_size));
974        Ok(Vcpu {
975            fd: fd,
976            vm: vm,
977            mmap: m,
978        })
979    }
980
981    /// Run the `Vcpu`
982    pub unsafe fn run(&mut self) -> Result<Run> {
983        let ret = kvm_run(self.fd.as_raw_fd());
984        if ret == 0 {
985            Ok(*(self.mmap.mut_ptr() as *mut Run))
986        } else {
987            Err(Error::last_os_error())
988        }
989    }
990
991    /// Get registers
992    pub fn get_regs(&self) -> Result<Regs> {
993        let mut regs = Regs::default();
994        let ret = unsafe { kvm_get_regs(self.fd.as_raw_fd(), &mut regs) };
995        if ret == 0 {
996            Ok(regs)
997        } else {
998            Err(Error::last_os_error())
999        }
1000    }
1001
1002    /// Set registers
1003    pub fn set_regs(&mut self, regs: &Regs) -> Result<()> {
1004        let ret = unsafe { kvm_set_regs(self.fd.as_raw_fd(), regs) };
1005        if ret == 0 {
1006            Ok(())
1007        } else {
1008            Err(Error::last_os_error())
1009        }
1010    }
1011}
1012
1013#[cfg(target_arch = "x86_64")]
1014impl<'a> Vcpu<'a> {
1015    /// Set the response to the CPUID instruction
1016    pub fn set_cpuid2(&mut self, cpuid: &mut Cpuid2) -> Result<()> {
1017        let ptr: *mut Cpuid2 = cpuid;
1018        let ret = unsafe { kvm_set_cpuid2(self.fd.as_raw_fd(), ptr) };
1019        if ret == 0 {
1020            Ok(())
1021        } else {
1022            Err(Error::last_os_error())
1023        }
1024    }
1025    /// Get special registers
1026    pub fn get_sregs(&self) -> Result<Sregs> {
1027        let mut sregs = Sregs::default();
1028        let ret = unsafe { kvm_get_sregs(self.fd.as_raw_fd(), &mut sregs) };
1029        if ret == 0 {
1030            Ok(sregs)
1031        } else {
1032            Err(Error::last_os_error())
1033        }
1034    }
1035    /// Set special registers
1036    pub fn set_sregs(&mut self, sregs: &Sregs) -> Result<()> {
1037        let ret = unsafe { kvm_set_sregs(self.fd.as_raw_fd(), sregs) };
1038        if ret == 0 {
1039            Ok(())
1040        } else {
1041            Err(Error::last_os_error())
1042        }
1043    }
1044}
1045
1046#[test]
1047fn init_test() {
1048    System::initialize().unwrap();
1049}
1050
1051#[test]
1052fn check_capability_test() {
1053    let h = System::initialize().unwrap();
1054    assert!(h.check_capability(Capability::UserMemory) != 0);
1055}
1056
1057#[test]
1058fn vcpus_test() {
1059    let h = System::initialize().unwrap();
1060    assert!(h.max_vcpus() >= h.recommended_vcpus());
1061}
1062
1063#[test]
1064fn create_vm_test() {
1065    let h = System::initialize().unwrap();
1066    VirtualMachine::create(&h).unwrap();
1067}
1068
1069#[test]
1070fn set_memory_test() {
1071    let mut anon_mmap = Mmap::anonymous(16 * (1 << 12), Protection::ReadWrite)
1072                            .unwrap();
1073    let slice = unsafe { anon_mmap.as_mut_slice() };
1074    let h = System::initialize().unwrap();
1075    let mut vm = VirtualMachine::create(&h).unwrap();
1076    vm.set_user_memory_region(0, slice, 0).unwrap();
1077}
1078
1079#[test]
1080fn create_vcpu_test() {
1081    let h = System::initialize().unwrap();
1082    let mut vm = VirtualMachine::create(&h).unwrap();
1083    Vcpu::create(&mut vm).unwrap();
1084}
1085
1086#[cfg(target_arch = "x86_64")]
1087#[test]
1088fn cpuid_test() {
1089    let h = System::initialize().unwrap();
1090    if h.check_capability(Capability::ExtCpuid) == 1 {
1091        let mut cpuid = h.get_supported_cpuid().unwrap();
1092        let mut vm = VirtualMachine::create(&h).unwrap();
1093        let mut vcpu = Vcpu::create(&mut vm).unwrap();
1094        vcpu.set_cpuid2(&mut cpuid).unwrap();
1095    }
1096}
1097
1098#[cfg(target_arch = "x86_64")]
1099#[test]
1100fn sreg_test() {
1101    let h = System::initialize().unwrap();
1102    let mut vm = VirtualMachine::create(&h).unwrap();
1103    let mut vcpu = Vcpu::create(&mut vm).unwrap();
1104    let mut sregs = vcpu.get_sregs().unwrap();
1105    sregs.cr0 = 0x1;
1106    vcpu.set_sregs(&sregs).unwrap();
1107    assert!(vcpu.get_sregs().unwrap().cr0 == 0x1);
1108}
1109
1110#[cfg(target_arch = "x86_64")]
1111#[test]
1112fn reg_test() {
1113    let h = System::initialize().unwrap();
1114    let mut vm = VirtualMachine::create(&h).unwrap();
1115    let mut vcpu = Vcpu::create(&mut vm).unwrap();
1116    let mut regs = vcpu.get_regs().unwrap();
1117    regs.rax = 0x1;
1118    vcpu.set_regs(&regs).unwrap();
1119    assert!(vcpu.get_regs().unwrap().rax == 0x1);
1120}