aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/kvm_sys.rs
diff options
context:
space:
mode:
authorjohannst <johannes.stoelp@gmail.com>2021-05-26 00:21:06 +0200
committerjohannst <johannes.stoelp@gmail.com>2021-05-26 00:21:06 +0200
commit786a195f8e81d4f7c0af2a82b9d458361d424a71 (patch)
treec0df3de9a71e3ae1db1cdf4a59cde6d1accadf33 /src/kvm_sys.rs
downloadmini-kvm-rs-786a195f8e81d4f7c0af2a82b9d458361d424a71.tar.gz
mini-kvm-rs-786a195f8e81d4f7c0af2a82b9d458361d424a71.zip
minimal KVM abstraction + real mode guest example
Diffstat (limited to 'src/kvm_sys.rs')
-rw-r--r--src/kvm_sys.rs248
1 files changed, 248 insertions, 0 deletions
diff --git a/src/kvm_sys.rs b/src/kvm_sys.rs
new file mode 100644
index 0000000..8d5c85b
--- /dev/null
+++ b/src/kvm_sys.rs
@@ -0,0 +1,248 @@
+#![allow(non_snake_case)]
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
+
+// Generated by `build.rs`.
+include!(concat!(env!("OUT_DIR"), "/kvm_constants.rs"));
+
+use std::fmt;
+
+#[repr(C)]
+#[derive(Default, Debug)]
+pub struct Rflags(pub u64);
+
+#[repr(C)]
+#[derive(Default, Debug)]
+pub struct kvm_regs {
+ pub rax: u64,
+ pub rbx: u64,
+ pub rcx: u64,
+ pub rdx: u64,
+ pub rsi: u64,
+ pub rdi: u64,
+ pub rsp: u64,
+ pub rbp: u64,
+ pub r8: u64,
+ pub r9: u64,
+ pub r10: u64,
+ pub r11: u64,
+ pub r12: u64,
+ pub r13: u64,
+ pub r14: u64,
+ pub r15: u64,
+ pub rip: u64,
+ pub rflags: Rflags,
+}
+
+#[repr(C)]
+#[derive(Default, Debug)]
+pub struct kvm_segment {
+ pub base: u64,
+ pub limit: u32,
+ pub selector: u16,
+ pub type_: u8,
+ pub present: u8,
+ pub dpl: u8,
+ pub db: u8,
+ pub s: u8,
+ pub l: u8,
+ pub g: u8,
+ pub avl: u8,
+ unusable: u8,
+ _padding: u8,
+}
+
+#[repr(C)]
+#[derive(Default, Debug)]
+pub struct kvm_dtable {
+ pub base: u64,
+ pub limit: u16,
+ _padding: [u16; 3],
+}
+
+#[repr(C)]
+#[derive(Default, Debug)]
+pub struct kvm_sregs {
+ pub cs: kvm_segment,
+ pub ds: kvm_segment,
+ pub es: kvm_segment,
+ pub fs: kvm_segment,
+ pub gs: kvm_segment,
+ pub ss: kvm_segment,
+ pub tr: kvm_segment,
+ pub ldt: kvm_segment,
+ pub gdt: kvm_dtable,
+ pub idt: kvm_dtable,
+ pub cr0: u64,
+ cr2: u64,
+ pub cr3: u64,
+ pub cr4: u64,
+ pub cr8: u64,
+ pub effer: u64,
+ pub apic_base: u64,
+ pub interrupt_bitmap: [u64; 4],
+}
+
+#[repr(C)]
+#[derive(Default, Debug)]
+pub(crate) struct kvm_userspace_memory_region {
+ pub slot: u32,
+ pub flags: u32,
+ pub guest_phys_addr: u64,
+ pub memory_size: u64,
+ pub userspace_addr: u64,
+}
+
+#[repr(C)]
+pub(crate) struct kvm_run {
+ request_interrupt_window: u8,
+ immediate_exit: u8,
+ padding1: [u8; 6],
+ pub exit_reason: u32,
+ ready_for_interrupt_injection: u8,
+ if_flag: u8,
+ flags: u16,
+ cr8: u64,
+ apic_base: u64,
+ pub inner: kvm_run_union,
+ kvm_valid_regs: u64,
+ kvm_dirty_regs: u64,
+ s: kvm_run_union_s,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub(crate) struct kvm_run_io {
+ pub direction: u8,
+ pub size: u8,
+ pub port: u16,
+ pub count: u32,
+ pub data_offset: u64,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub(crate) struct kvm_run_mmio {
+ pub phys_addr: u64,
+ pub data: [u8; 8],
+ pub len: u32,
+ pub is_write: u8,
+}
+
+// Only add the union fields used here.
+#[repr(C)]
+pub(crate) union kvm_run_union {
+ pub io: kvm_run_io,
+ pub mmio: kvm_run_mmio,
+ padding: [u8; 256],
+}
+
+// Only add the union fields used here.
+#[repr(C)]
+union kvm_run_union_s {
+ padding: [u8; 2048],
+}
+
+// {{{ Display : Rflags
+
+impl fmt::Display for Rflags {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let IF = || (self.0 >> 9) & 0b1;
+ let IOPL = || (self.0 >> 12) & 0b11;
+ let AC = || (self.0 >> 19) & 0b1;
+ write!(f, "AC({}) IOPL({}) IF({})", AC(), IOPL(), IF())
+ }
+}
+
+// }}}
+// {{{ Display : kvm_regs
+
+impl fmt::Display for kvm_regs {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "rax: {:#018x} rbx: {:#018x} rcx: {:#018x} rdx: {:#018x}\n\
+ rsi: {:#018x} rdi: {:#018x}\n\
+ r8 : {:#018x} r9 : {:#018x} r10: {:#018x} r11: {:#018x}\n\
+ r12: {:#018x} r13: {:#018x} r14: {:#018x} r15: {:#018x}\n\
+ rsp: {:#018x} rbp: {:#018x}\n\
+ rip: {:#018x} rflags: {:#018x} [{}]",
+ self.rax,
+ self.rbx,
+ self.rcx,
+ self.rdx,
+ self.rsi,
+ self.rdi,
+ self.r8,
+ self.r9,
+ self.r10,
+ self.r11,
+ self.r12,
+ self.r13,
+ self.r14,
+ self.r15,
+ self.rsp,
+ self.rbp,
+ self.rip,
+ self.rflags.0,
+ self.rflags
+ )
+ }
+}
+
+// }}}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use std::mem;
+
+ #[test]
+ fn check_kvm_regs() {
+ assert_eq!(mem::size_of::<kvm_regs>(), TEST_KVM_REGS_SIZE);
+ assert_eq!(mem::align_of::<kvm_regs>(), TEST_KVM_REGS_ALIGN);
+ }
+
+ #[test]
+ fn check_kvm_segment() {
+ assert_eq!(mem::size_of::<kvm_segment>(), TEST_KVM_SEGMENT_SIZE);
+ assert_eq!(mem::align_of::<kvm_segment>(), TEST_KVM_SEGMENT_ALIGN);
+ }
+
+ #[test]
+ fn check_kvm_dtable() {
+ assert_eq!(mem::size_of::<kvm_dtable>(), TEST_KVM_DTABLE_SIZE);
+ assert_eq!(mem::align_of::<kvm_dtable>(), TEST_KVM_DTABLE_ALIGN);
+ }
+
+ #[test]
+ fn check_kvm_sregs() {
+ assert_eq!(mem::size_of::<kvm_sregs>(), TEST_KVM_SREGS_SIZE);
+ assert_eq!(mem::align_of::<kvm_sregs>(), TEST_KVM_SREGS_ALIGN);
+ assert_eq!(
+ mem::size_of_val(&kvm_sregs::default().interrupt_bitmap),
+ TEST_KVM_SREGS_INTERRTUP_BITMAP_SIZE
+ );
+ }
+
+ #[test]
+ fn check_kvm_userspace_memory_region() {
+ assert_eq!(
+ mem::size_of::<kvm_userspace_memory_region>(),
+ TEST_KVM_USERSPACE_MEMORY_REGION_SIZE
+ );
+ assert_eq!(
+ mem::align_of::<kvm_userspace_memory_region>(),
+ TEST_KVM_USERSPACE_MEMORY_REGION_ALIGN
+ );
+ }
+
+ #[test]
+ fn check_kvm_run() {
+ assert_eq!(mem::size_of::<kvm_run>(), TEST_KVM_RUN_SIZE);
+ assert_eq!(mem::align_of::<kvm_run>(), TEST_KVM_RUN_ALIGN);
+ assert_eq!(mem::size_of::<kvm_run_io>(), TEST_KVM_RUN_IO_SIZE);
+ assert_eq!(mem::size_of::<kvm_run_mmio>(), TEST_KVM_RUN_MMIO_SIZE);
+ assert_eq!(mem::size_of::<kvm_run_union_s>(), TEST_KVM_RUN_UNION_S_SIZE);
+ }
+}