From ae16a6d75f8c953b839af755512dc06fc6090025 Mon Sep 17 00:00:00 2001 From: novafacing Date: Mon, 3 Jun 2024 10:28:08 -0700 Subject: [PATCH] Fix some typos and add conditional API for V3 --- .github/workflows/ci.yml | 2 +- plugins/tracer/src/lib.rs | 39 ++-- qemu-plugin-sys/generate-bindings.rs | 9 +- qemu-plugin-sys/src/bindings_v3.rs | 40 +++- qemu-plugin-sys/src/qemu_plugin_api_v3.def | 2 + qemu-plugin/src/lib.rs | 214 ++++++++++++++++++--- 6 files changed, 261 insertions(+), 45 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13c7895..8b8e800 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -170,7 +170,7 @@ jobs: container: ubuntu:24.04 env: # Hash of v3 - QEMU_COMMIT_HASH: 4abc892362f8282450f18c4e45c5b0534461d01e + QEMU_COMMIT_HASH: 7de77d37880d7267a491cb32a1b2232017d1e545 steps: - name: Set up Sources List run: | diff --git a/plugins/tracer/src/lib.rs b/plugins/tracer/src/lib.rs index 6405578..b0d8ada 100644 --- a/plugins/tracer/src/lib.rs +++ b/plugins/tracer/src/lib.rs @@ -149,19 +149,17 @@ impl Tracer { } impl HasCallbacks for Tracer { + #[cfg(any(feature = "plugin-api-v2", feature = "plugin-api-v3"))] fn on_vcpu_init( &mut self, _id: PluginId, _vcpu_id: VCPUIndex, ) -> std::prelude::v1::Result<(), anyhow::Error> { - #[cfg(any(feature = "plugin-api-v2", feature = "plugin-api-v3"))] - { - *self - .registers - .lock() - .map_err(|e| anyhow!("Failed to lock registers: {}", e))? = - qemu_plugin_get_registers()?; - } + *self + .registers + .lock() + .map_err(|e| anyhow!("Failed to lock registers: {}", e))? = + qemu_plugin_get_registers()?; Ok(()) } @@ -173,6 +171,27 @@ impl HasCallbacks for Tracer { tb.instructions().try_for_each(|insn| { let event = InstructionEvent::try_from(&insn)?; + #[cfg(feature = "plugin-api-v1")] + if self.log_insns { + let tx = self.tx.clone(); + + insn.register_execute_callback(move |_| { + tx.lock() + .map_err(|e| anyhow!("Failed to lock tx: {}", e)) + .and_then(|tx| { + to_writer( + tx.as_ref().ok_or_else(|| anyhow!("No tx"))?, + &Event::Instruction { + event: event.clone(), + }, + ) + .map_err(|e| anyhow!(e)) + }) + .expect("Failed to send instruction event"); + }); + } + + #[cfg(any(feature = "plugin-api-v2", feature = "plugin-api-v3"))] if self.log_insns { let tx = self.tx.clone(); let registers = self @@ -189,10 +208,6 @@ impl HasCallbacks for Tracer { tx.as_ref().ok_or_else(|| anyhow!("No tx"))?, &Event::Instruction { event: event.clone(), - #[cfg(any( - feature = "plugin-api-v2", - feature = "plugin-api-v3" - ))] registers: Registers( registers .iter() diff --git a/qemu-plugin-sys/generate-bindings.rs b/qemu-plugin-sys/generate-bindings.rs index 5584680..335e44c 100755 --- a/qemu-plugin-sys/generate-bindings.rs +++ b/qemu-plugin-sys/generate-bindings.rs @@ -36,8 +36,8 @@ const QEMU_SRC_URL_BASE: &str = "https://download.qemu.org/"; const QEMU_VERSION_V1: &str = "8.2.4"; // Plugin V2 is from 9.0.0 const QEMU_VERSION_V2: &str = "9.0.0"; -/// Plugin V3 is from 4abc892362f8282450f18c4e45c5b0534461d01e -const QEMU_VERSION_V3: &str = "4abc892362f8282450f18c4e45c5b0534461d01e"; +/// Plugin V3 is from 7de77d37880d7267a491cb32a1b2232017d1e545 +const QEMU_VERSION_V3: &str = "7de77d37880d7267a491cb32a1b2232017d1e545"; fn qemu_src_url_v1() -> String { format!("{}qemu-{}.tar.xz", QEMU_SRC_URL_BASE, QEMU_VERSION_V1) @@ -48,7 +48,7 @@ fn qemu_src_url_v2() -> String { } fn qemu_src_url_v3() -> String { - format!("{}/archive/4abc892362f8282450f18c4e45c5b0534461d01e.zip", QEMU_GITHUB_URL_BASE) + format!("{}/archive/{}.zip", QEMU_GITHUB_URL_BASE, QEMU_VERSION_V3) } /// Download a URL to a destination, using a blocking request @@ -91,7 +91,7 @@ fn extract_txz(archive: &Path, destination: &Path) -> Result<()> { Ok(()) } -/// Extract a zip frile at a path to a destination +/// Extract a zip file at a path to a destination fn extract_zip(archive: &Path, destination: &Path) -> Result<()> { let archive = File::open(archive)?; let mut archive = ZipArchive::new(archive)?; @@ -108,7 +108,6 @@ fn generate_windows_delaylink_library(qemu_plugin_symbols: &Path, destination: & } fn generate_bindings(qemu_plugin_header: &Path, destination: &Path) -> Result<()> { - // let glib_20 = probe_library("glib-2.0").map_err(|e| anyhow!(e))?; let header_contents = read_to_string(qemu_plugin_header)?; let header_file_name = qemu_plugin_header.file_name().ok_or_else(|| anyhow!("Failed to get file name"))?.to_str().ok_or_else(|| anyhow!("Failed to convert file name to string"))?; let header_contents = header_contents.replace("#include ", ""); diff --git a/qemu-plugin-sys/src/bindings_v3.rs b/qemu-plugin-sys/src/bindings_v3.rs index 747a67e..3d09443 100644 --- a/qemu-plugin-sys/src/bindings_v3.rs +++ b/qemu-plugin-sys/src/bindings_v3.rs @@ -185,6 +185,19 @@ pub enum qemu_plugin_mem_rw { QEMU_PLUGIN_MEM_W = 2, QEMU_PLUGIN_MEM_RW = 3, } +#[repr(u32)] +#[doc = " enum qemu_plugin_cond - condition to enable callback\n\n @QEMU_PLUGIN_COND_NEVER: false\n @QEMU_PLUGIN_COND_ALWAYS: true\n @QEMU_PLUGIN_COND_EQ: is equal?\n @QEMU_PLUGIN_COND_NE: is not equal?\n @QEMU_PLUGIN_COND_LT: is less than?\n @QEMU_PLUGIN_COND_LE: is less than or equal?\n @QEMU_PLUGIN_COND_GT: is greater than?\n @QEMU_PLUGIN_COND_GE: is greater than or equal?"] +#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub enum qemu_plugin_cond { + QEMU_PLUGIN_COND_NEVER = 0, + QEMU_PLUGIN_COND_ALWAYS = 1, + QEMU_PLUGIN_COND_EQ = 2, + QEMU_PLUGIN_COND_NE = 3, + QEMU_PLUGIN_COND_LT = 4, + QEMU_PLUGIN_COND_LE = 5, + QEMU_PLUGIN_COND_GT = 6, + QEMU_PLUGIN_COND_GE = 7, +} #[doc = " typedef qemu_plugin_vcpu_tb_trans_cb_t - translation callback\n @id: unique plugin id\n @tb: opaque handle used for querying and instrumenting a block."] pub type qemu_plugin_vcpu_tb_trans_cb_t = ::std::option::Option; @@ -204,11 +217,24 @@ extern "C" { userdata: *mut ::std::os::raw::c_void, ); } +extern "C" { + #[doc = " qemu_plugin_register_vcpu_tb_exec_cond_cb() - register conditional callback\n @tb: the opaque qemu_plugin_tb handle for the translation\n @cb: callback function\n @cond: condition to enable callback\n @entry: first operand for condition\n @imm: second operand for condition\n @flags: does the plugin read or write the CPU's registers?\n @userdata: any plugin data to pass to the @cb?\n\n The @cb function is called when a translated unit executes if\n entry @cond imm is true.\n If condition is QEMU_PLUGIN_COND_ALWAYS, condition is never interpreted and\n this function is equivalent to qemu_plugin_register_vcpu_tb_exec_cb.\n If condition QEMU_PLUGIN_COND_NEVER, condition is never interpreted and\n callback is never installed."] + pub fn qemu_plugin_register_vcpu_tb_exec_cond_cb( + tb: *mut qemu_plugin_tb, + cb: qemu_plugin_vcpu_udata_cb_t, + flags: qemu_plugin_cb_flags, + cond: qemu_plugin_cond, + entry: qemu_plugin_u64, + imm: u64, + userdata: *mut ::std::os::raw::c_void, + ); +} #[repr(u32)] -#[doc = " enum qemu_plugin_op - describes an inline op\n\n @QEMU_PLUGIN_INLINE_ADD_U64: add an immediate value uint64_t\n\n Note: currently only a single inline op is supported."] +#[doc = " enum qemu_plugin_op - describes an inline op\n\n @QEMU_PLUGIN_INLINE_ADD_U64: add an immediate value uint64_t\n @QEMU_PLUGIN_INLINE_STORE_U64: store an immediate value uint64_t"] #[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] pub enum qemu_plugin_op { QEMU_PLUGIN_INLINE_ADD_U64 = 0, + QEMU_PLUGIN_INLINE_STORE_U64 = 1, } extern "C" { #[doc = " qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu() - execution inline op\n @tb: the opaque qemu_plugin_tb handle for the translation\n @op: the type of qemu_plugin_op (e.g. ADD_U64)\n @entry: entry to run op\n @imm: the op data (e.g. 1)\n\n Insert an inline op on a given scoreboard entry."] @@ -228,6 +254,18 @@ extern "C" { userdata: *mut ::std::os::raw::c_void, ); } +extern "C" { + #[doc = " qemu_plugin_register_vcpu_insn_exec_cond_cb() - conditional insn execution cb\n @insn: the opaque qemu_plugin_insn handle for an instruction\n @cb: callback function\n @flags: does the plugin read or write the CPU's registers?\n @cond: condition to enable callback\n @entry: first operand for condition\n @imm: second operand for condition\n @userdata: any plugin data to pass to the @cb?\n\n The @cb function is called when an instruction executes if\n entry @cond imm is true.\n If condition is QEMU_PLUGIN_COND_ALWAYS, condition is never interpreted and\n this function is equivalent to qemu_plugin_register_vcpu_insn_exec_cb.\n If condition QEMU_PLUGIN_COND_NEVER, condition is never interpreted and\n callback is never installed."] + pub fn qemu_plugin_register_vcpu_insn_exec_cond_cb( + insn: *mut qemu_plugin_insn, + cb: qemu_plugin_vcpu_udata_cb_t, + flags: qemu_plugin_cb_flags, + cond: qemu_plugin_cond, + entry: qemu_plugin_u64, + imm: u64, + userdata: *mut ::std::os::raw::c_void, + ); +} extern "C" { #[doc = " qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu() - insn exec inline op\n @insn: the opaque qemu_plugin_insn handle for an instruction\n @op: the type of qemu_plugin_op (e.g. ADD_U64)\n @entry: entry to run op\n @imm: the op data (e.g. 1)\n\n Insert an inline op to every time an instruction executes."] pub fn qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu( diff --git a/qemu-plugin-sys/src/qemu_plugin_api_v3.def b/qemu-plugin-sys/src/qemu_plugin_api_v3.def index a11358a..ece395c 100644 --- a/qemu-plugin-sys/src/qemu_plugin_api_v3.def +++ b/qemu-plugin-sys/src/qemu_plugin_api_v3.def @@ -28,6 +28,7 @@ EXPORTS qemu_plugin_register_vcpu_idle_cb qemu_plugin_register_vcpu_init_cb qemu_plugin_register_vcpu_insn_exec_cb + qemu_plugin_register_vcpu_insn_exec_cond_cb qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu qemu_plugin_register_vcpu_mem_cb qemu_plugin_register_vcpu_mem_inline_per_vcpu @@ -35,6 +36,7 @@ EXPORTS qemu_plugin_register_vcpu_syscall_cb qemu_plugin_register_vcpu_syscall_ret_cb qemu_plugin_register_vcpu_tb_exec_cb + qemu_plugin_register_vcpu_tb_exec_cond_cb qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu qemu_plugin_register_vcpu_tb_trans_cb qemu_plugin_reset diff --git a/qemu-plugin/src/lib.rs b/qemu-plugin/src/lib.rs index 0430925..59bd49f 100644 --- a/qemu-plugin/src/lib.rs +++ b/qemu-plugin/src/lib.rs @@ -83,6 +83,8 @@ mod win_link_hook; use crate::error::{Error, Result}; #[cfg(feature = "num-traits")] use num_traits::{FromBytes, PrimInt}; +#[cfg(feature = "plugin-api-v3")] +use qemu_plugin_sys::qemu_plugin_cond; use qemu_plugin_sys::{ qemu_plugin_cb_flags, qemu_plugin_hwaddr, qemu_plugin_id_t, qemu_plugin_insn, qemu_plugin_mem_rw, qemu_plugin_meminfo_t, qemu_plugin_op, qemu_plugin_simple_cb_t, @@ -239,13 +241,16 @@ pub type VCPUIndex = c_uint; /// u64 member of an entry in a scoreboard, allows access to a specific u64 member in /// one given entry, located at a specified offset. Inline operations expect this as an /// entry. -pub type QemuPluginU64 = qemu_plugin_u64; +pub type PluginU64 = qemu_plugin_u64; /// Flags for callbacks pub type CallbackFlags = qemu_plugin_cb_flags; /// Memory read/write flags pub type MemRW = qemu_plugin_mem_rw; +#[cfg(any(feature = "plugin-api-v3"))] +/// A condition for a callback to be run +pub type PluginCondition = qemu_plugin_cond; /// Plugin operations for inline operations -pub type QemuPluginOp = qemu_plugin_op; +pub type PluginOp = qemu_plugin_op; /// A plugin ID pub type PluginId = qemu_plugin_id_t; @@ -410,6 +415,57 @@ impl<'a> TranslationBlock<'a> { ) }; } + + #[cfg(feature = "plugin-api-v3")] + /// Register a callback to be conditionally run on execution of this translation + /// block + pub fn register_conditional_execute_callback( + &self, + cb: F, + cond: PluginCondition, + entry: PluginU64, + immediate: u64, + ) where + F: FnMut(VCPUIndex) + Send + Sync + 'static, + { + self.register_conditional_execute_callback_flags( + cb, + CallbackFlags::QEMU_PLUGIN_CB_NO_REGS, + cond, + entry, + immediate, + ) + } + + #[cfg(feature = "plugin-api-v3")] + /// Register a callback to be conditionally run on execution of this translation + /// block + pub fn register_conditional_execute_callback_flags( + &self, + cb: F, + flags: CallbackFlags, + cond: PluginCondition, + entry: PluginU64, + immediate: u64, + ) where + F: FnMut(VCPUIndex) + Send + Sync + 'static, + { + let callback = Box::new(cb); + let callback_box = Box::new(callback); + let userdata = Box::into_raw(callback_box) as *mut c_void; + + unsafe { + crate::sys::qemu_plugin_register_vcpu_tb_exec_cond_cb( + self.translation_block as *mut qemu_plugin_tb, + Some(handle_qemu_plugin_register_vcpu_tb_exec_cb::), + flags, + cond, + entry, + immediate, + userdata, + ) + }; + } } /// An iterator over the instructions of a translation block @@ -463,10 +519,10 @@ impl<'a> Instruction<'a> { /// Returns the data for this instruction. This method may only be called inside the /// callback in which the instruction is obtained, but the resulting data is owned. pub fn data(&self) -> Vec { - println!("data 1"); let size = self.size(); let mut data = Vec::with_capacity(size); + // NOTE: The name of this API doesn't change, but its parameters and return value *do* let insn_data = unsafe { crate::sys::qemu_plugin_insn_data(self.instruction as *mut qemu_plugin_insn) } as *mut u8; @@ -486,6 +542,7 @@ impl<'a> Instruction<'a> { let size = self.size(); let mut data = vec![0; size]; + // NOTE: The name of this API doesn't change, but its parameters and return value *do* let size = unsafe { crate::sys::qemu_plugin_insn_data( self.instruction as *mut qemu_plugin_insn, @@ -574,6 +631,55 @@ impl<'a> Instruction<'a> { }; } + /// Register a callback to be conditionally run on execution of this instruction + #[cfg(feature = "plugin-api-v3")] + pub fn register_conditional_execute_callback( + &self, + cb: F, + cond: PluginCondition, + entry: PluginU64, + immediate: u64, + ) where + F: FnMut(VCPUIndex) + Send + Sync + 'static, + { + self.register_conditional_execute_callback_flags( + cb, + CallbackFlags::QEMU_PLUGIN_CB_NO_REGS, + cond, + entry, + immediate, + ) + } + + /// Register a callback to be conditionally run on execution of this instruction + #[cfg(feature = "plugin-api-v3")] + pub fn register_conditional_execute_callback_flags( + &self, + cb: F, + flags: CallbackFlags, + cond: PluginCondition, + entry: PluginU64, + immediate: u64, + ) where + F: FnMut(VCPUIndex) + Send + Sync + 'static, + { + let callback = Box::new(cb); + let callback_box = Box::new(callback); + let userdata = Box::into_raw(callback_box) as *mut c_void; + + unsafe { + crate::sys::qemu_plugin_register_vcpu_insn_exec_cond_cb( + self.instruction as *mut qemu_plugin_insn, + Some(handle_qemu_plugin_register_vcpu_insn_exec_cb::), + flags, + cond, + entry, + immediate, + userdata, + ) + }; + } + /// Register a callback to be run on memory access of this instruction /// /// # Arguments @@ -1090,11 +1196,39 @@ extern "C" fn handle_qemu_plugin_register_vcpu_tb_exec_cb( /// /// This function is safe when the pointer `tb` is a valid pointer to a `qemu_plugin_tb` /// structure, which is always opaque. -pub fn qemu_plugin_register_vcpu_tb_exec_cb(tb: TranslationBlock, cb: F) +pub fn qemu_plugin_register_vcpu_tb_exec_cb(tb: TranslationBlock, cb: F, flags: CallbackFlags) where F: FnMut(VCPUIndex) + Send + Sync + 'static, { - tb.register_execute_callback(cb); + tb.register_execute_callback_flags(cb, flags); +} + +#[cfg(feature = "plugin-api-v3")] +/// Register a callback to be conditionally called when a translation block is executed. +/// +/// # Arguments +/// +/// - `tb`: The translated block to register the execution callback for +/// - `cb`: The callback to be called when the block `tb` is executed +/// - `cond`: The condition to be met for the callback to be called +/// - `entry`: The entry to be passed to the callback +/// - `immediate`: The immediate value to be passed to the callback +/// +/// # Safety +/// +/// This function is safe when the pointer `tb` is a valid pointer to a `qemu_plugin_tb` +/// structure, which is always opaque. +pub fn qemu_plugin_register_vcpu_tb_exec_cond_cb( + tb: TranslationBlock, + cb: F, + flags: CallbackFlags, + cond: PluginCondition, + entry: PluginU64, + immediate: u64, +) where + F: FnMut(VCPUIndex) + Send + Sync + 'static, +{ + tb.register_conditional_execute_callback_flags(cb, flags, cond, entry, immediate); } #[cfg(feature = "plugin-api-v1")] @@ -1109,7 +1243,7 @@ where /// - `imm`: The immediate value to be passed to the operation pub fn qemu_plugin_register_vcpu_tb_exec_inline( tb: TranslationBlock, - op: QemuPluginOp, + op: PluginOp, ptr: *mut c_void, imm: u64, ) { @@ -1135,8 +1269,8 @@ pub fn qemu_plugin_register_vcpu_tb_exec_inline( /// - `imm`: The immediate value to be passed to the operation pub fn qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu( tb: TranslationBlock, - op: QemuPluginOp, - entry: QemuPluginU64, + op: PluginOp, + entry: PluginU64, imm: u64, ) { unsafe { @@ -1168,11 +1302,35 @@ extern "C" fn handle_qemu_plugin_register_vcpu_insn_exec_cb( /// /// - `insn`: The instruction handle to register the callback for /// - `cb`: The callback to be called -pub fn qemu_plugin_register_vcpu_insn_exec_cb(insn: Instruction, cb: F) +pub fn qemu_plugin_register_vcpu_insn_exec_cb(insn: Instruction, cb: F, flags: CallbackFlags) where F: FnMut(VCPUIndex) + Send + Sync + 'static, { - insn.register_execute_callback(cb); + insn.register_execute_callback_flags(cb, flags); +} + +#[cfg(feature = "plugin-api-v3")] +#[allow(clippy::not_unsafe_ptr_arg_deref)] +/// Register a callback to be conditionally called when an instruction is executed. +/// +/// # Arguments +/// +/// - `insn`: The instruction handle to register the callback for +/// - `cb`: The callback to be called +/// - `cond`: The condition to be met for the callback to be called +/// - `entry`: The entry to be passed to the callback +/// - `immediate`: The immediate value to be passed to the callback +pub fn qemu_plugin_register_vcpu_insn_exec_cond_cb( + insn: Instruction, + cb: F, + flags: CallbackFlags, + cond: PluginCondition, + entry: PluginU64, + immediate: u64, +) where + F: FnMut(VCPUIndex) + Send + Sync + 'static, +{ + insn.register_conditional_execute_callback_flags(cb, flags, cond, entry, immediate); } #[cfg(feature = "plugin-api-v1")] @@ -1187,7 +1345,7 @@ where /// - `imm`: The immediate value to be passed to the operation pub fn qemu_plugin_register_vcpu_insn_exec_inline( insn: Instruction, - op: QemuPluginOp, + op: PluginOp, ptr: *mut c_void, imm: u64, ) { @@ -1213,8 +1371,8 @@ pub fn qemu_plugin_register_vcpu_insn_exec_inline( /// - `imm`: The immediate value to be passed to the operation pub fn qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu( insn: Instruction, - op: QemuPluginOp, - entry: QemuPluginU64, + op: PluginOp, + entry: PluginU64, imm: u64, ) { unsafe { @@ -1250,11 +1408,15 @@ extern "C" fn handle_qemu_plugin_register_vcpu_mem_cb( /// - `insn`: The instruction handle to register the callback for /// - `cb`: The callback to be called /// - `rw`: Whether the callback should be called for reads, writes, or both -pub fn qemu_plugin_register_vcpu_mem_cb(insn: Instruction, cb: F, rw: MemRW) -where +pub fn qemu_plugin_register_vcpu_mem_cb( + insn: Instruction, + cb: F, + flags: CallbackFlags, + rw: MemRW, +) where F: FnMut(VCPUIndex, MemoryInfo, u64) + Send + Sync + 'static, { - insn.register_memory_access_callback(cb, rw); + insn.register_memory_access_callback_flags(cb, rw, flags); } #[cfg(feature = "plugin-api-v1")] @@ -1271,7 +1433,7 @@ where pub fn qemu_plugin_register_vcpu_mem_inline( insn: Instruction, rw: MemRW, - op: QemuPluginOp, + op: PluginOp, ptr: *mut c_void, imm: u64, ) { @@ -1300,8 +1462,8 @@ pub fn qemu_plugin_register_vcpu_mem_inline( pub fn qemu_plugin_register_vcpu_mem_inline_per_vcpu( insn: Instruction, rw: MemRW, - op: QemuPluginOp, - entry: QemuPluginU64, + op: PluginOp, + entry: PluginU64, imm: u64, ) { unsafe { @@ -1542,26 +1704,26 @@ pub fn qemu_plugin_get_registers<'a>() -> Result>> { } #[cfg(any(feature = "plugin-api-v2", feature = "plugin-api-v3"))] -/// Add a value to a `QemuPluginU64` for a given VCPU -pub fn qemu_plugin_u64_add(entry: QemuPluginU64, vcpu_index: VCPUIndex, added: u64) -> Result<()> { +/// Add a value to a `PluginU64` for a given VCPU +pub fn qemu_plugin_u64_add(entry: PluginU64, vcpu_index: VCPUIndex, added: u64) -> Result<()> { unsafe { crate::sys::qemu_plugin_u64_add(entry, vcpu_index, added) }; Ok(()) } #[cfg(any(feature = "plugin-api-v2", feature = "plugin-api-v3"))] -/// Get the value of a `QemuPluginU64` for a given VCPU -pub fn qemu_plugin_u64_get(entry: QemuPluginU64, vcpu_index: VCPUIndex) -> u64 { +/// Get the value of a `PluginU64` for a given VCPU +pub fn qemu_plugin_u64_get(entry: PluginU64, vcpu_index: VCPUIndex) -> u64 { unsafe { crate::sys::qemu_plugin_u64_get(entry, vcpu_index) } } #[cfg(any(feature = "plugin-api-v2", feature = "plugin-api-v3"))] -/// Set the value of a `QemuPluginU64` for a given VCPU -pub fn qemu_plugin_u64_set(entry: QemuPluginU64, vcpu_index: VCPUIndex, value: u64) { +/// Set the value of a `PluginU64` for a given VCPU +pub fn qemu_plugin_u64_set(entry: PluginU64, vcpu_index: VCPUIndex, value: u64) { unsafe { crate::sys::qemu_plugin_u64_set(entry, vcpu_index, value) } } #[cfg(any(feature = "plugin-api-v2", feature = "plugin-api-v3"))] /// Get the sum of all VCPU entries in a scoreboard -pub fn qemu_plugin_scoreboard_sum(entry: QemuPluginU64) -> u64 { +pub fn qemu_plugin_scoreboard_sum(entry: PluginU64) -> u64 { unsafe { crate::sys::qemu_plugin_u64_sum(entry) } }