diff options
Diffstat (limited to 'rust/qemu-api')
| -rw-r--r-- | rust/qemu-api/Cargo.toml | 1 | ||||
| -rw-r--r-- | rust/qemu-api/meson.build | 7 | ||||
| -rw-r--r-- | rust/qemu-api/src/bindings.rs | 14 | ||||
| -rw-r--r-- | rust/qemu-api/src/lib.rs | 1 | ||||
| -rw-r--r-- | rust/qemu-api/src/memory.rs | 200 | ||||
| -rw-r--r-- | rust/qemu-api/src/sysbus.rs | 2 | ||||
| -rw-r--r-- | rust/qemu-api/wrapper.h | 3 |
7 files changed, 7 insertions, 221 deletions
diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml index 3bf2dafa6d..2884c1d460 100644 --- a/rust/qemu-api/Cargo.toml +++ b/rust/qemu-api/Cargo.toml @@ -20,6 +20,7 @@ migration = { path = "../migration" } util = { path = "../util" } bql = { path = "../bql" } qom = { path = "../qom" } +system = { path = "../system" } qemu_api_macros = { path = "../qemu-api-macros" } [lints] diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index a47f178b69..92e2581a64 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -8,7 +8,6 @@ c_enums = [ 'MachineInitPhase', 'MemoryDeviceInfoKind', 'ResetType', - 'device_endian', ] _qemu_api_bindgen_args = [] foreach enum : c_enums @@ -24,8 +23,11 @@ endforeach blocked_type = [ 'Chardev', 'Error', + 'MemTxAttrs', + 'MemoryRegion', 'ObjectClass', 'VMStateDescription', + 'device_endian', ] foreach type: blocked_type _qemu_api_bindgen_args += ['--blocklist-type', type] @@ -54,7 +56,6 @@ _qemu_api_rs = static_library( 'src/lib.rs', 'src/bindings.rs', 'src/irq.rs', - 'src/memory.rs', 'src/prelude.rs', 'src/qdev.rs', 'src/sysbus.rs', @@ -65,7 +66,7 @@ _qemu_api_rs = static_library( rust_abi: 'rust', rust_args: _qemu_api_cfg, dependencies: [anyhow_rs, bql_rs, chardev_rs, common_rs, foreign_rs, libc_rs, migration_rs, qemu_api_macros, - qom_rs, util_rs, hwcore], + qom_rs, system_rs, util_rs, hwcore], ) qemu_api_rs = declare_dependency(link_with: [_qemu_api_rs], diff --git a/rust/qemu-api/src/bindings.rs b/rust/qemu-api/src/bindings.rs index 526bcf8e31..63b805c76e 100644 --- a/rust/qemu-api/src/bindings.rs +++ b/rust/qemu-api/src/bindings.rs @@ -24,6 +24,7 @@ use chardev::bindings::Chardev; use common::Zeroable; use migration::bindings::VMStateDescription; use qom::bindings::ObjectClass; +use system::bindings::{device_endian, MemTxAttrs, MemoryRegion}; use util::bindings::Error; #[cfg(MESON)] @@ -32,15 +33,6 @@ include!("bindings.inc.rs"); #[cfg(not(MESON))] include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs")); -// SAFETY: this is a pure data struct -unsafe impl Send for CoalescedMemoryRange {} -unsafe impl Sync for CoalescedMemoryRange {} - -// SAFETY: these are constants and vtables; the Send and Sync requirements -// are deferred to the unsafe callbacks that they contain -unsafe impl Send for MemoryRegionOps {} -unsafe impl Sync for MemoryRegionOps {} - unsafe impl Send for Property {} unsafe impl Sync for Property {} @@ -49,7 +41,3 @@ unsafe impl Sync for TypeInfo {} unsafe impl Zeroable for crate::bindings::Property__bindgen_ty_1 {} unsafe impl Zeroable for crate::bindings::Property {} -unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_1 {} -unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_2 {} -unsafe impl Zeroable for crate::bindings::MemoryRegionOps {} -unsafe impl Zeroable for crate::bindings::MemTxAttrs {} diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index d96096899d..8d57440478 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -14,7 +14,6 @@ pub mod bindings; pub mod prelude; pub mod irq; -pub mod memory; pub mod qdev; pub mod sysbus; diff --git a/rust/qemu-api/src/memory.rs b/rust/qemu-api/src/memory.rs deleted file mode 100644 index ecbbd9b604..0000000000 --- a/rust/qemu-api/src/memory.rs +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2024 Red Hat, Inc. -// Author(s): Paolo Bonzini <pbonzini@redhat.com> -// SPDX-License-Identifier: GPL-2.0-or-later - -//! Bindings for `MemoryRegion`, `MemoryRegionOps` and `MemTxAttrs` - -use std::{ - ffi::{c_uint, c_void, CStr, CString}, - marker::PhantomData, -}; - -pub use bindings::{hwaddr, MemTxAttrs}; -use common::{callbacks::FnCall, uninit::MaybeUninitField, zeroable::Zeroable, Opaque}; -use qom::prelude::*; - -use crate::bindings::{self, device_endian, memory_region_init_io}; - -pub struct MemoryRegionOps<T>( - bindings::MemoryRegionOps, - // Note: quite often you'll see PhantomData<fn(&T)> mentioned when discussing - // covariance and contravariance; you don't need any of those to understand - // this usage of PhantomData. Quite simply, MemoryRegionOps<T> *logically* - // holds callbacks that take an argument of type &T, except the type is erased - // before the callback is stored in the bindings::MemoryRegionOps field. - // The argument of PhantomData is a function pointer in order to represent - // that relationship; while that will also provide desirable and safe variance - // for T, variance is not the point but just a consequence. - PhantomData<fn(&T)>, -); - -// SAFETY: When a *const T is passed to the callbacks, the call itself -// is done in a thread-safe manner. The invocation is okay as long as -// T itself is `Sync`. -unsafe impl<T: Sync> Sync for MemoryRegionOps<T> {} - -#[derive(Clone)] -pub struct MemoryRegionOpsBuilder<T>(bindings::MemoryRegionOps, PhantomData<fn(&T)>); - -unsafe extern "C" fn memory_region_ops_read_cb<T, F: for<'a> FnCall<(&'a T, hwaddr, u32), u64>>( - opaque: *mut c_void, - addr: hwaddr, - size: c_uint, -) -> u64 { - F::call((unsafe { &*(opaque.cast::<T>()) }, addr, size)) -} - -unsafe extern "C" fn memory_region_ops_write_cb<T, F: for<'a> FnCall<(&'a T, hwaddr, u64, u32)>>( - opaque: *mut c_void, - addr: hwaddr, - data: u64, - size: c_uint, -) { - F::call((unsafe { &*(opaque.cast::<T>()) }, addr, data, size)) -} - -impl<T> MemoryRegionOpsBuilder<T> { - #[must_use] - pub const fn read<F: for<'a> FnCall<(&'a T, hwaddr, u32), u64>>(mut self, _f: &F) -> Self { - self.0.read = Some(memory_region_ops_read_cb::<T, F>); - self - } - - #[must_use] - pub const fn write<F: for<'a> FnCall<(&'a T, hwaddr, u64, u32)>>(mut self, _f: &F) -> Self { - self.0.write = Some(memory_region_ops_write_cb::<T, F>); - self - } - - #[must_use] - pub const fn big_endian(mut self) -> Self { - self.0.endianness = device_endian::DEVICE_BIG_ENDIAN; - self - } - - #[must_use] - pub const fn little_endian(mut self) -> Self { - self.0.endianness = device_endian::DEVICE_LITTLE_ENDIAN; - self - } - - #[must_use] - pub const fn native_endian(mut self) -> Self { - self.0.endianness = device_endian::DEVICE_NATIVE_ENDIAN; - self - } - - #[must_use] - pub const fn valid_sizes(mut self, min: u32, max: u32) -> Self { - self.0.valid.min_access_size = min; - self.0.valid.max_access_size = max; - self - } - - #[must_use] - pub const fn valid_unaligned(mut self) -> Self { - self.0.valid.unaligned = true; - self - } - - #[must_use] - pub const fn impl_sizes(mut self, min: u32, max: u32) -> Self { - self.0.impl_.min_access_size = min; - self.0.impl_.max_access_size = max; - self - } - - #[must_use] - pub const fn impl_unaligned(mut self) -> Self { - self.0.impl_.unaligned = true; - self - } - - #[must_use] - pub const fn build(self) -> MemoryRegionOps<T> { - MemoryRegionOps::<T>(self.0, PhantomData) - } - - #[must_use] - pub const fn new() -> Self { - Self(bindings::MemoryRegionOps::ZERO, PhantomData) - } -} - -impl<T> Default for MemoryRegionOpsBuilder<T> { - fn default() -> Self { - Self::new() - } -} - -/// A safe wrapper around [`bindings::MemoryRegion`]. -#[repr(transparent)] -#[derive(qemu_api_macros::Wrapper)] -pub struct MemoryRegion(Opaque<bindings::MemoryRegion>); - -unsafe impl Send for MemoryRegion {} -unsafe impl Sync for MemoryRegion {} - -impl MemoryRegion { - // inline to ensure that it is not included in tests, which only - // link to hwcore and qom. FIXME: inlining is actually the opposite - // of what we want, since this is the type-erased version of the - // init_io function below. Look into splitting the qemu_api crate. - #[inline(always)] - unsafe fn do_init_io( - slot: *mut bindings::MemoryRegion, - owner: *mut bindings::Object, - ops: &'static bindings::MemoryRegionOps, - name: &'static str, - size: u64, - ) { - unsafe { - let cstr = CString::new(name).unwrap(); - memory_region_init_io( - slot, - owner, - ops, - owner.cast::<c_void>(), - cstr.as_ptr(), - size, - ); - } - } - - pub fn init_io<T: IsA<Object>>( - this: &mut MaybeUninitField<'_, T, Self>, - ops: &'static MemoryRegionOps<T>, - name: &'static str, - size: u64, - ) { - unsafe { - Self::do_init_io( - this.as_mut_ptr().cast(), - MaybeUninitField::parent_mut(this).cast(), - &ops.0, - name, - size, - ); - } - } -} - -unsafe impl ObjectType for MemoryRegion { - type Class = bindings::MemoryRegionClass; - const TYPE_NAME: &'static CStr = - unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_MEMORY_REGION) }; -} - -qom_isa!(MemoryRegion: Object); - -/// A special `MemTxAttrs` constant, used to indicate that no memory -/// attributes are specified. -/// -/// Bus masters which don't specify any attributes will get this, -/// which has all attribute bits clear except the topmost one -/// (so that we can distinguish "all attributes deliberately clear" -/// from "didn't specify" if necessary). -pub const MEMTXATTRS_UNSPECIFIED: MemTxAttrs = MemTxAttrs { - unspecified: true, - ..Zeroable::ZERO -}; diff --git a/rust/qemu-api/src/sysbus.rs b/rust/qemu-api/src/sysbus.rs index b883d7eaf1..dda71ebda7 100644 --- a/rust/qemu-api/src/sysbus.rs +++ b/rust/qemu-api/src/sysbus.rs @@ -9,11 +9,11 @@ use std::{ffi::CStr, ptr::addr_of_mut}; pub use bindings::SysBusDeviceClass; use common::Opaque; use qom::{prelude::*, Owned}; +use system::MemoryRegion; use crate::{ bindings, irq::{IRQState, InterruptSource}, - memory::MemoryRegion, qdev::{DeviceImpl, DeviceState}, }; diff --git a/rust/qemu-api/wrapper.h b/rust/qemu-api/wrapper.h index 07dbc9987a..564733b903 100644 --- a/rust/qemu-api/wrapper.h +++ b/rust/qemu-api/wrapper.h @@ -49,14 +49,11 @@ typedef enum memory_order { #include "qemu/osdep.h" #include "qemu-io.h" -#include "system/system.h" #include "hw/sysbus.h" -#include "system/memory.h" #include "hw/clock.h" #include "hw/qdev-clock.h" #include "hw/qdev-properties.h" #include "hw/qdev-properties-system.h" #include "hw/irq.h" #include "exec/memattrs.h" -#include "system/address-spaces.h" #include "hw/char/pl011.h" |