diff options
author | johannst <johannes.stoelp@gmail.com> | 2021-05-26 00:21:06 +0200 |
---|---|---|
committer | johannst <johannes.stoelp@gmail.com> | 2021-05-26 00:21:06 +0200 |
commit | 786a195f8e81d4f7c0af2a82b9d458361d424a71 (patch) | |
tree | c0df3de9a71e3ae1db1cdf4a59cde6d1accadf33 /src/kvm_sys.rs | |
download | mini-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.rs | 248 |
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); + } +} |