diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a1dc2ea --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "typeinfo": "cpp" + } +} \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 8a112c3..9c4e257 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,4 +14,7 @@ categories = ["api-bindings"] [dependencies] libloading = "0.6.1" log = "0.4.8" -xenctrl-sys = { git = "https://github.com/Wenzel/xenctrl-sys.git" } +xenctrl-sys = { git = "https://github.com/arnabcs17b006/xenctrl-sys.git", branch = "default_derive" } +xenvmevent-sys = { git = "https://github.com/arnabcs17b006/xenvmevent-sys.git", branch="derive_default" } +enum-primitive-derive = "0.1.2" +num-traits = "0.2.8" diff --git a/src/lib.rs b/src/lib.rs index 945832c..26a440b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,22 +7,128 @@ mod macros; extern crate xenctrl_sys; +use self::consts::{PAGE_SHIFT, PAGE_SIZE}; +use enum_primitive_derive::Primitive; +use error::XcError; +use libxenctrl::LibXenCtrl; +use num_traits::FromPrimitive; +use std::io::Error; use std::{ - convert::TryInto, + alloc::{alloc_zeroed, Layout}, + convert::{From, TryFrom, TryInto}, ffi, ffi::c_void, mem, + os::raw::c_uint, ptr::{null_mut, NonNull}, + slice, }; - -use libxenctrl::LibXenCtrl; -use xenctrl_sys::{ - hvm_hw_cpu, xc_error_code, xc_interface, xen_pfn_t, xentoollog_logger, __HVM_SAVE_TYPE_CPU, +pub use xenctrl_sys::{hvm_hw_cpu, hvm_save_descriptor, xentoollog_logger, __HVM_SAVE_TYPE_CPU}; +use xenctrl_sys::{xc_error_code, xc_interface, xenmem_access_t}; +pub use xenvmevent_sys::{ + vm_event_back_ring, vm_event_request_t, vm_event_response_t, vm_event_sring, +}; +use xenvmevent_sys::{ + MEM_ACCESS_R, MEM_ACCESS_RW, MEM_ACCESS_RWX, MEM_ACCESS_RX, MEM_ACCESS_W, MEM_ACCESS_WX, + MEM_ACCESS_X, VM_EVENT_REASON_MEM_ACCESS, VM_EVENT_REASON_MOV_TO_MSR, + VM_EVENT_REASON_SINGLESTEP, VM_EVENT_REASON_SOFTWARE_BREAKPOINT, VM_EVENT_REASON_WRITE_CTRLREG, + VM_EVENT_X86_CR0, VM_EVENT_X86_CR3, VM_EVENT_X86_CR4, }; -use error::XcError; +#[derive(Copy, Clone, Debug)] +#[repr(u32)] +pub enum XenPageAccess { + NIL, + R, + W, + RW, + X, + RX, + WX, + RWX, +} + +impl TryFrom for XenPageAccess { + type Error = &'static str; + fn try_from(flag: u32) -> Result { + match flag { + 0 => Ok(XenPageAccess::NIL), + MEM_ACCESS_R => Ok(XenPageAccess::R), + MEM_ACCESS_W => Ok(XenPageAccess::W), + MEM_ACCESS_RW => Ok(XenPageAccess::RW), + MEM_ACCESS_X => Ok(XenPageAccess::X), + MEM_ACCESS_RX => Ok(XenPageAccess::RX), + MEM_ACCESS_WX => Ok(XenPageAccess::WX), + MEM_ACCESS_RWX => Ok(XenPageAccess::RWX), + _ => Err("invalid access value"), + } + } +} + +impl TryFrom for XenPageAccess { + type Error = &'static str; + fn try_from(access: xenmem_access_t) -> Result { + match access { + xenmem_access_t::XENMEM_access_n => Ok(XenPageAccess::NIL), + xenmem_access_t::XENMEM_access_r => Ok(XenPageAccess::R), + xenmem_access_t::XENMEM_access_w => Ok(XenPageAccess::W), + xenmem_access_t::XENMEM_access_rw => Ok(XenPageAccess::RW), + xenmem_access_t::XENMEM_access_x => Ok(XenPageAccess::X), + xenmem_access_t::XENMEM_access_rx => Ok(XenPageAccess::RX), + xenmem_access_t::XENMEM_access_wx => Ok(XenPageAccess::WX), + xenmem_access_t::XENMEM_access_rwx => Ok(XenPageAccess::RWX), + _ => Err("not implemented"), + } + } +} + +impl From for xenmem_access_t { + fn from(access: XenPageAccess) -> Self { + match access { + XenPageAccess::NIL => xenmem_access_t::XENMEM_access_n, + XenPageAccess::R => xenmem_access_t::XENMEM_access_r, + XenPageAccess::W => xenmem_access_t::XENMEM_access_w, + XenPageAccess::RW => xenmem_access_t::XENMEM_access_rw, + XenPageAccess::X => xenmem_access_t::XENMEM_access_x, + XenPageAccess::RX => xenmem_access_t::XENMEM_access_rx, + XenPageAccess::WX => xenmem_access_t::XENMEM_access_wx, + XenPageAccess::RWX => xenmem_access_t::XENMEM_access_rwx, + } + } +} -type Result = std::result::Result; +#[derive(Primitive, Debug, Copy, Clone, PartialEq)] +#[repr(u32)] +pub enum XenCr { + Cr0 = VM_EVENT_X86_CR0, + Cr3 = VM_EVENT_X86_CR3, + Cr4 = VM_EVENT_X86_CR4, +} + +#[derive(Debug, Copy, Clone)] +pub enum XenEventType { + Cr { + cr_type: XenCr, + new: u64, + old: u64, + }, + Msr { + msr_type: u32, + value: u64, + }, + Breakpoint { + gpa: u64, + insn_len: u8, + }, + Pagefault { + gva: u64, + gpa: u64, + access: XenPageAccess, + }, + Singlestep { + gpa: u64, + }, +} #[derive(Debug)] pub struct XenControl { @@ -30,43 +136,106 @@ pub struct XenControl { libxenctrl: LibXenCtrl, } -impl XenControl { - pub fn new( +pub trait XenIntrospectable: std::fmt::Debug { + fn init( + &mut self, logger: Option<&mut xentoollog_logger>, dombuild_logger: Option<&mut xentoollog_logger>, open_flags: u32, - ) -> Result { - let libxenctrl = unsafe { LibXenCtrl::new() }; + ) -> Result<(), XcError>; + fn domain_hvm_getcontext_partial(&self, domid: u32, vcpu: u16) -> Result; + fn domain_hvm_setcontext( + &self, + domid: u32, + buffer: *mut c_uint, + size: usize, + ) -> Result<(), XcError>; + fn domain_hvm_getcontext( + &self, + domid: u32, + vcpu: u16, + ) -> Result<(*mut c_uint, hvm_hw_cpu, u32), XcError>; + fn monitor_enable( + &mut self, + domid: u32, + ) -> Result<(vm_event_sring, vm_event_back_ring, u32), XcError>; + fn get_request( + &self, + back_ring: &mut vm_event_back_ring, + ) -> Result; + fn put_response( + &self, + rsp: &mut vm_event_response_t, + back_ring: &mut vm_event_back_ring, + ) -> Result<(), XcError>; + fn get_event_type(&self, req: vm_event_request_t) -> Result; + fn monitor_disable(&self, domid: u32) -> Result<(), XcError>; + fn domain_pause(&self, domid: u32) -> Result<(), XcError>; + fn domain_unpause(&self, domid: u32) -> Result<(), XcError>; + fn monitor_software_breakpoint(&self, domid: u32, enable: bool) -> Result<(), XcError>; + fn monitor_singlestep(&self, domid: u32, enable: bool) -> Result<(), XcError>; + fn monitor_mov_to_msr(&self, domid: u32, msr: u32, enable: bool) -> Result<(), XcError>; + fn monitor_write_ctrlreg( + &self, + domid: u32, + index: XenCr, + enable: bool, + sync: bool, + onchangeonly: bool, + ) -> Result<(), XcError>; + fn set_mem_access( + &self, + domid: u32, + access: XenPageAccess, + first_pfn: u64, + ) -> Result<(), XcError>; + fn get_mem_access(&self, domid: u32, pfn: u64) -> Result; + fn domain_maximum_gpfn(&self, domid: u32) -> Result; + fn close(&mut self) -> Result<(), XcError>; +} - let xc_handle = (libxenctrl.interface_open)( - logger.map_or_else(null_mut, |l| l as *mut _), - dombuild_logger.map_or_else(null_mut, |l| l as *mut _), - open_flags, - ); +pub fn create_xen_control() -> XenControl { + XenControl::new(unsafe { LibXenCtrl::new() }) +} - NonNull::new(xc_handle) - .ok_or_else(|| { - let desc = (libxenctrl.error_code_to_desc)(xc_error_code::XC_INTERNAL_ERROR as _); - XcError::new(unsafe { ffi::CStr::from_ptr(desc) }.to_str().unwrap()) - }) - .map(|handle| XenControl { handle, libxenctrl }) +impl XenControl { + fn new(libxenctrl: LibXenCtrl) -> XenControl { + XenControl { + handle: NonNull::dangling(), + libxenctrl, + } } +} - pub fn default() -> Result { - Self::new(None, None, 0) +impl XenIntrospectable for XenControl { + fn init( + &mut self, + logger: Option<&mut xentoollog_logger>, + dombuild_logger: Option<&mut xentoollog_logger>, + open_flags: u32, + ) -> Result<(), XcError> { + #[allow(clippy::redundant_closure)] + let xc_handle = (self.libxenctrl.interface_open)( + logger.map_or_else(|| null_mut(), |l| l as *mut _), + dombuild_logger.map_or_else(|| null_mut(), |l| l as *mut _), + open_flags, + ); + + self.handle = NonNull::new(xc_handle).unwrap(); + last_error!(self, ()) } - pub fn domain_hvm_getcontext_partial(&self, domid: u32, vcpu: u16) -> Result { + fn domain_hvm_getcontext_partial(&self, domid: u32, vcpu: u16) -> Result { let xc = self.handle.as_ptr(); let mut hvm_cpu: hvm_hw_cpu = unsafe { mem::MaybeUninit::::zeroed().assume_init() }; // cast to mut c_void* let hvm_cpu_ptr = &mut hvm_cpu as *mut _ as *mut c_void; - // #define HVM_SAVE_CODE(_x) (sizeof (((struct __HVM_SAVE_TYPE_##_x *)(0))->c)) - let hvm_save_type_cpu = - unsafe { mem::MaybeUninit::<__HVM_SAVE_TYPE_CPU>::zeroed().assume_init() }; - let hvm_save_code_cpu: u16 = mem::size_of_val(&hvm_save_type_cpu.c).try_into().unwrap(); let hvm_size: u32 = mem::size_of::().try_into().unwrap(); + let hvm_save_cpu = + unsafe { mem::MaybeUninit::<__HVM_SAVE_TYPE_CPU>::zeroed().assume_init() }; + let hvm_save_code_cpu: u16 = mem::size_of_val(&hvm_save_cpu.c).try_into().unwrap(); + (self.libxenctrl.clear_last_error)(xc); (self.libxenctrl.domain_hvm_getcontext_partial)( xc, @@ -79,45 +248,270 @@ impl XenControl { last_error!(self, hvm_cpu) } - pub fn monitor_enable(&mut self, domid: u32) -> Result<(*mut c_void, u32)> { + fn domain_hvm_setcontext( + &self, + domid: u32, + buffer: *mut c_uint, + size: usize, + ) -> Result<(), XcError> { + let xc = self.handle.as_ptr(); + (self.libxenctrl.clear_last_error)(xc); + (self.libxenctrl.domain_hvm_setcontext)(xc, domid, buffer, size.try_into().unwrap()); + last_error!(self, ()) + } + + fn domain_hvm_getcontext( + &self, + domid: u32, + vcpu: u16, + ) -> Result<(*mut c_uint, hvm_hw_cpu, u32), XcError> { + let xc = self.handle.as_ptr(); + (self.libxenctrl.clear_last_error)(xc); + let size = + (self.libxenctrl.domain_hvm_getcontext)(xc, domid, std::ptr::null_mut::(), 0); + let layout = + Layout::from_size_align(size.try_into().unwrap(), mem::align_of::()).unwrap(); + #[allow(clippy::cast_ptr_alignment)] + let buffer = unsafe { alloc_zeroed(layout) as *mut c_uint }; + (self.libxenctrl.clear_last_error)(xc); + (self.libxenctrl.domain_hvm_getcontext)(xc, domid, buffer, size.try_into().unwrap()); + let mut offset: u32 = 0; + let hvm_save_cpu = + unsafe { mem::MaybeUninit::<__HVM_SAVE_TYPE_CPU>::zeroed().assume_init() }; + let hvm_save_code_cpu: u16 = mem::size_of_val(&hvm_save_cpu.c).try_into().unwrap(); + let mut cpu_ptr: *mut hvm_hw_cpu = std::ptr::null_mut(); + unsafe { + while offset < size.try_into().unwrap() { + let buffer_ptr = buffer as usize; + let descriptor: *mut hvm_save_descriptor = + (buffer_ptr + offset as usize) as *mut hvm_save_descriptor; + let diff: u32 = mem::size_of::().try_into().unwrap(); + offset += diff; + if (*descriptor).typecode == hvm_save_code_cpu && (*descriptor).instance == vcpu { + cpu_ptr = (buffer_ptr + offset as usize) as *mut hvm_hw_cpu; + break; + } + + offset += (*descriptor).length; + } + } + last_error!(self, (buffer, *cpu_ptr, size.try_into().unwrap())) + } + + fn monitor_enable( + &mut self, + domid: u32, + ) -> Result<(vm_event_sring, vm_event_back_ring, u32), XcError> { let xc = self.handle.as_ptr(); let mut remote_port: u32 = 0; (self.libxenctrl.clear_last_error)(xc); - let ring_page: *mut c_void = + let void_ring_page: *mut c_void = (self.libxenctrl.monitor_enable)(xc, domid.try_into().unwrap(), &mut remote_port); - last_error!(self, (ring_page, remote_port)) + let ring_page = void_ring_page as *mut vm_event_sring; + unsafe { + (*ring_page).req_prod = 0; + (*ring_page).rsp_prod = 0; + (*ring_page).req_event = 1; + (*ring_page).rsp_event = 1; + (*ring_page).pvt.pvt_pad = mem::MaybeUninit::zeroed().assume_init(); + (*ring_page).__pad = mem::MaybeUninit::zeroed().assume_init(); + } + // BACK_RING_INIT(&back_ring, ring_page, XC_PAGE_SIZE); + let mut back_ring: vm_event_back_ring = + unsafe { mem::MaybeUninit::::zeroed().assume_init() }; + back_ring.rsp_prod_pvt = 0; + back_ring.req_cons = 0; + back_ring.nr_ents = __RING_SIZE!(ring_page, PAGE_SIZE); + back_ring.sring = ring_page; + last_error!(self, (*ring_page, back_ring, remote_port)) + } + + fn get_request( + &self, + back_ring: &mut vm_event_back_ring, + ) -> Result { + let mut req_cons = back_ring.req_cons; + let req_from_ring = RING_GET_REQUEST!(back_ring, req_cons); + req_cons += 1; + back_ring.req_cons = req_cons; + unsafe { + (*(back_ring.sring)).req_event = 1 + req_cons; + } + last_error!(self, req_from_ring) + } + + fn put_response( + &self, + rsp: &mut vm_event_response_t, + back_ring: &mut vm_event_back_ring, + ) -> Result<(), XcError> { + let mut rsp_prod = back_ring.rsp_prod_pvt; + let rsp_dereferenced = *rsp; + RING_PUT_RESPONSE!(back_ring, rsp_prod, rsp_dereferenced); + rsp_prod += 1; + back_ring.rsp_prod_pvt = rsp_prod; + RING_PUSH_RESPONSES!(back_ring); + last_error!(self, ()) + } + + fn get_event_type(&self, req: vm_event_request_t) -> Result { + let ev_type: XenEventType; + unsafe { + ev_type = match req.reason { + VM_EVENT_REASON_WRITE_CTRLREG => XenEventType::Cr { + cr_type: XenCr::from_i32(req.u.write_ctrlreg.index.try_into().unwrap()) + .unwrap(), + new: req.u.write_ctrlreg.new_value, + old: req.u.write_ctrlreg.old_value, + }, + VM_EVENT_REASON_MOV_TO_MSR => XenEventType::Msr { + msr_type: req.u.mov_to_msr.msr.try_into().unwrap(), + value: req.u.mov_to_msr.value, + }, + VM_EVENT_REASON_SOFTWARE_BREAKPOINT => XenEventType::Breakpoint { + gpa: req.u.software_breakpoint.gfn << PAGE_SHIFT, + insn_len: req.u.software_breakpoint.insn_length.try_into().unwrap(), + }, + VM_EVENT_REASON_MEM_ACCESS => XenEventType::Pagefault { + gva: req.u.mem_access.gla, + gpa: req.u.mem_access.gfn << PAGE_SHIFT, + access: { + let mut flag = req.u.mem_access.flags; + if flag >= 32 { + flag -= 32; + } + if flag >= 16 { + flag -= 16; + } + if flag >= 8 { + flag -= 8; + } + flag.try_into().unwrap() + }, + }, + VM_EVENT_REASON_SINGLESTEP => XenEventType::Singlestep { + gpa: req.u.singlestep.gfn << PAGE_SHIFT, + }, + _ => unimplemented!(), + }; + } + last_error!(self, ev_type) } - pub fn monitor_disable(&self, domid: u32) -> Result<()> { + fn monitor_disable(&self, domid: u32) -> Result<(), XcError> { let xc = self.handle.as_ptr(); (self.libxenctrl.clear_last_error)(xc); (self.libxenctrl.monitor_disable)(xc, domid.try_into().unwrap()); last_error!(self, ()) } - pub fn domain_pause(&self, domid: u32) -> Result<()> { + fn domain_pause(&self, domid: u32) -> Result<(), XcError> { let xc = self.handle.as_ptr(); (self.libxenctrl.clear_last_error)(xc); (self.libxenctrl.domain_pause)(xc, domid); last_error!(self, ()) } - pub fn domain_unpause(&self, domid: u32) -> Result<()> { + fn domain_unpause(&self, domid: u32) -> Result<(), XcError> { let xc = self.handle.as_ptr(); (self.libxenctrl.clear_last_error)(xc); (self.libxenctrl.domain_unpause)(xc, domid); last_error!(self, ()) } - pub fn domain_maximum_gpfn(&self, domid: u32) -> Result { + fn monitor_software_breakpoint(&self, domid: u32, enable: bool) -> Result<(), XcError> { + let xc = self.handle.as_ptr(); + (self.libxenctrl.clear_last_error)(xc); + let rc = (self.libxenctrl.monitor_software_breakpoint)(xc, domid, enable); + if rc < 0 { + println!("last OS error: {:?}", Error::last_os_error()); + } + last_error!(self, ()) + } + + fn monitor_singlestep(&self, domid: u32, enable: bool) -> Result<(), XcError> { + let xc = self.handle.as_ptr(); + (self.libxenctrl.clear_last_error)(xc); + let rc = (self.libxenctrl.monitor_singlestep)(xc, domid, enable); + if rc < 0 { + println!("last OS error: {:?}", Error::last_os_error()); + } + last_error!(self, ()) + } + + fn monitor_mov_to_msr(&self, domid: u32, msr: u32, enable: bool) -> Result<(), XcError> { + let xc = self.handle.as_ptr(); + (self.libxenctrl.clear_last_error)(xc); + let rc = (self.libxenctrl.monitor_mov_to_msr)(xc, domid.try_into().unwrap(), msr, enable); + if rc < 0 { + println!("last OS error: {:?}", Error::last_os_error()); + } + last_error!(self, ()) + } + + fn monitor_write_ctrlreg( + &self, + domid: u32, + index: XenCr, + enable: bool, + sync: bool, + onchangeonly: bool, + ) -> Result<(), XcError> { + let xc = self.handle.as_ptr(); + (self.libxenctrl.clear_last_error)(xc); + let rc = (self.libxenctrl.monitor_write_ctrlreg)( + xc, + domid.try_into().unwrap(), + index as u16, + enable, + sync, + onchangeonly, + ); + if rc < 0 { + println!("last OS error: {:?}", Error::last_os_error()); + } + last_error!(self, ()) + } + + fn set_mem_access( + &self, + domid: u32, + access: XenPageAccess, + first_pfn: u64, + ) -> Result<(), XcError> { + let xc = self.handle.as_ptr(); + (self.libxenctrl.clear_last_error)(xc); + (self.libxenctrl.set_mem_access)( + xc, + domid.try_into().unwrap(), + access.into(), + first_pfn, + 1, + ); + last_error!(self, ()) + } + + fn get_mem_access(&self, domid: u32, pfn: u64) -> Result { + let xc = self.handle.as_ptr(); + let mut access: xenmem_access_t = xenmem_access_t::XENMEM_access_n; + (self.libxenctrl.clear_last_error)(xc); + (self.libxenctrl.get_mem_access)(xc, domid.try_into().unwrap(), pfn, &mut access); + last_error!(self, access.try_into().unwrap()) + } + + fn domain_maximum_gpfn(&self, domid: u32) -> Result { let xc = self.handle.as_ptr(); + #[allow(unused_assignments)] + let mut max_gpfn = mem::MaybeUninit::::uninit(); (self.libxenctrl.clear_last_error)(xc); - let mut max_gpfn: xen_pfn_t = unsafe { mem::MaybeUninit::zeroed().assume_init() }; - (self.libxenctrl.domain_maximum_gpfn)(xc, domid.try_into().unwrap(), &mut max_gpfn); - last_error!(self, max_gpfn) + unsafe { + max_gpfn = mem::MaybeUninit::zeroed().assume_init(); + } + (self.libxenctrl.domain_maximum_gpfn)(xc, domid.try_into().unwrap(), max_gpfn.as_mut_ptr()); + last_error!(self, max_gpfn.assume_init()) } - fn close(&mut self) -> Result<()> { + fn close(&mut self) -> Result<(), XcError> { let xc = self.handle.as_ptr(); (self.libxenctrl.clear_last_error)(xc); (self.libxenctrl.interface_close)(xc); diff --git a/src/libxenctrl.rs b/src/libxenctrl.rs index 476958e..4ab7f6a 100644 --- a/src/libxenctrl.rs +++ b/src/libxenctrl.rs @@ -1,6 +1,6 @@ use std::os::raw::{c_char, c_int, c_uint, c_void}; -use xenctrl_sys::{domid_t, xc_error, xc_interface, xen_pfn_t, xentoollog_logger}; +use xenctrl_sys::{domid_t, xc_error, xc_interface, xen_pfn_t, xenmem_access_t, xentoollog_logger}; use libloading::{os::unix::Symbol as RawSymbol, Library, Symbol}; use log::info; @@ -27,6 +27,12 @@ type FnDomainHVMGetcontextPartial = fn( ctxt_buf: *mut c_void, size: u32, ) -> c_int; +//xc_domain_hvm_getcontext +type FnDomainHVMGetcontext = + fn(xch: *mut xc_interface, domid: u32, ctxt_buf: *mut c_uint, size: u32) -> c_int; +//xc_domain_setcontext +type FnDomainHVMSetcontext = + fn(xch: *mut xc_interface, domid: u32, hvm_ctxt: *mut c_uint, size: u32) -> c_int; // xc_monitor_enable type FnMonitorEnable = fn(xch: *mut xc_interface, domain_id: domid_t, port: *mut u32) -> *mut c_void; @@ -41,6 +47,33 @@ type FnDomainMaximumGPFN = fn(xch: *mut xc_interface, domid: domid_t, gpfns: *mut xen_pfn_t) -> c_int; // xc_interface_close type FnInterfaceClose = fn(xch: *mut xc_interface) -> c_int; +//xc_monitor_software_breakpoint +type FnMonitorSoftwareBreakpoint = fn(xch: *mut xc_interface, domid: u32, enable: bool) -> c_int; +//xc_monitor_mov_to_msr +type FnMonitorMovToMsr = + fn(xch: *mut xc_interface, domain_id: domid_t, msr: u32, enable: bool) -> c_int; +//xc_monitor_singlestep +type FnMonitorSinglestep = fn(xch: *mut xc_interface, domid: u32, enable: bool) -> c_int; +//xc_monitor_write_ctrlreg +type FnMonitorWriteCtrlreg = fn( + xch: *mut xc_interface, + domain_id: domid_t, + index: u16, + enable: bool, + sync: bool, + onchangeonly: bool, +) -> c_int; +//xc_get_mem_access +type FnGetMemAccess = + fn(xch: *mut xc_interface, domain_id: domid_t, pfn: u64, access: *mut xenmem_access_t) -> c_int; +//xc_set_mem_access +type FnSetMemAccess = fn( + xch: *mut xc_interface, + domain_id: domid_t, + access: xenmem_access_t, + first_pfn: u64, + nr: u32, +) -> c_int; #[derive(Debug)] pub struct LibXenCtrl { @@ -50,12 +83,20 @@ pub struct LibXenCtrl { pub get_last_error: RawSymbol, pub error_code_to_desc: RawSymbol, pub domain_hvm_getcontext_partial: RawSymbol, + pub domain_hvm_getcontext: RawSymbol, + pub domain_hvm_setcontext: RawSymbol, pub monitor_enable: RawSymbol, pub monitor_disable: RawSymbol, pub domain_pause: RawSymbol, pub domain_unpause: RawSymbol, pub domain_maximum_gpfn: RawSymbol, pub interface_close: RawSymbol, + pub monitor_software_breakpoint: RawSymbol, + pub monitor_mov_to_msr: RawSymbol, + pub monitor_write_ctrlreg: RawSymbol, + pub get_mem_access: RawSymbol, + pub set_mem_access: RawSymbol, + pub monitor_singlestep: RawSymbol, } impl LibXenCtrl { @@ -81,6 +122,14 @@ impl LibXenCtrl { lib.get(b"xc_domain_hvm_getcontext_partial\0").unwrap(); let domain_hvm_getcontext_partial = domain_hvm_getcontext_partial_sym.into_raw(); + let domain_hvm_getcontext_sym: Symbol = + lib.get(b"xc_domain_hvm_getcontext\0").unwrap(); + let domain_hvm_getcontext = domain_hvm_getcontext_sym.into_raw(); + + let domain_hvm_setcontext_sym: Symbol = + lib.get(b"xc_domain_hvm_setcontext\0").unwrap(); + let domain_hvm_setcontext = domain_hvm_setcontext_sym.into_raw(); + let monitor_enable_sym: Symbol = lib.get(b"xc_monitor_enable\0").unwrap(); let monitor_enable = monitor_enable_sym.into_raw(); @@ -91,6 +140,28 @@ impl LibXenCtrl { let domain_pause_sym: Symbol = lib.get(b"xc_domain_pause\0").unwrap(); let domain_pause = domain_pause_sym.into_raw(); + let monitor_software_breakpoint_sym: Symbol = + lib.get(b"xc_monitor_software_breakpoint\0").unwrap(); + let monitor_software_breakpoint = monitor_software_breakpoint_sym.into_raw(); + + let monitor_mov_to_msr_sym: Symbol = + lib.get(b"xc_monitor_mov_to_msr\0").unwrap(); + let monitor_mov_to_msr = monitor_mov_to_msr_sym.into_raw(); + + let monitor_write_ctrlreg_sym: Symbol = + lib.get(b"xc_monitor_write_ctrlreg\0").unwrap(); + let monitor_write_ctrlreg = monitor_write_ctrlreg_sym.into_raw(); + + let monitor_singlestep_sym: Symbol = + lib.get(b"xc_monitor_singlestep\0").unwrap(); + let monitor_singlestep = monitor_singlestep_sym.into_raw(); + + let get_mem_access_sym: Symbol = lib.get(b"xc_get_mem_access\0").unwrap(); + let get_mem_access = get_mem_access_sym.into_raw(); + + let set_mem_access_sym: Symbol = lib.get(b"xc_set_mem_access\0").unwrap(); + let set_mem_access = set_mem_access_sym.into_raw(); + let domain_unpause_sym: Symbol = lib.get(b"xc_domain_unpause\0").unwrap(); let domain_unpause = domain_unpause_sym.into_raw(); @@ -109,8 +180,16 @@ impl LibXenCtrl { get_last_error, error_code_to_desc, domain_hvm_getcontext_partial, + domain_hvm_getcontext, + domain_hvm_setcontext, monitor_enable, monitor_disable, + monitor_software_breakpoint, + monitor_mov_to_msr, + monitor_write_ctrlreg, + get_mem_access, + set_mem_access, + monitor_singlestep, domain_pause, domain_unpause, domain_maximum_gpfn, diff --git a/src/macros.rs b/src/macros.rs index 83471ba..d8be3e2 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -12,3 +12,103 @@ macro_rules! last_error { } }; } + +macro_rules! __RING_SIZE { + ($name1: ident, $name2: ident) => { + unsafe { + __RD32!( + (($name2 as usize + $name1 as usize + - &mut (*$name1).ring[0] as *mut xenvmevent_sys::vm_event_sring_entry as usize) + / std::mem::size_of_val(&(*$name1).ring[0])) as u32 + ) + } + }; +} +macro_rules! __RD2 { + ($name: expr) => { + if $name as u32 & 0x00000002 != 0 { + 0x2 + } else { + $name as u32 & 0x1 + } + }; +} +macro_rules! __RD4 { + ($name: expr) => { + if $name as u32 & 0x0000000c != 0 { + __RD2!(($name) >> 2) << 2 + } else { + __RD2!($name) + } + }; +} +macro_rules! __RD8 { + ($name: expr) => { + if $name as u32 & 0x000000f0 != 0 { + __RD4!(($name) >> 4) << 4 + } else { + __RD4!($name) + } + }; +} +macro_rules! __RD16 { + ($name: expr) => { + if $name as u32 & 0x0000ff00 != 0 { + __RD8!(($name) >> 8) << 8 + } else { + __RD8!($name) + } + }; +} +macro_rules! __RD32 { + ($name: expr) => { + if $name as u32 & 0xffff0000 != 0 { + __RD16!(($name) >> 16) << 16 + } else { + __RD16!($name) + } + }; +} + +#[macro_export] +macro_rules! RING_HAS_UNCONSUMED_REQUESTS { + ($name: ident) => {{ + let req = unsafe { (*($name.sring)).req_prod - $name.req_cons }; + let rsp = $name.nr_ents - ($name.req_cons - $name.rsp_prod_pvt); + if req < rsp { + req + } else { + rsp + } + }}; +} + +macro_rules! RING_PUSH_RESPONSES { + ($name1: ident) => { + unsafe { + (*($name1.sring)).rsp_prod = $name1.rsp_prod_pvt; + } + }; +} + +macro_rules! RING_GET_REQUEST { + ($name1: ident, $name2: ident) => { + unsafe { + let ring_slice = + slice::from_raw_parts((*$name1.sring).ring.as_mut_ptr(), $name1.nr_ents as usize); + ring_slice[($name2 & ($name1.nr_ents - 1)) as usize].req + } + }; +} + +macro_rules! RING_PUT_RESPONSE { + ($name1: ident, $name2: ident, $name3: ident) => { + unsafe { + let ring_slice = slice::from_raw_parts_mut( + (*$name1.sring).ring.as_mut_ptr(), + $name1.nr_ents as usize, + ); + ring_slice[($name2 & ($name1.nr_ents - 1)) as usize].rsp = $name3; + } + }; +}