aboutsummaryrefslogtreecommitdiff
path: root/rust/hw/timer/hpet/src
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2025-06-21 10:00:46 -0400
committerStefan Hajnoczi <stefanha@redhat.com>2025-06-21 10:00:46 -0400
commit43ba160cb4bbb193560eb0d2d7decc4b5fc599fe (patch)
tree2a12561d9da7a4bee1ad5279fe8dd10f4432d74a /rust/hw/timer/hpet/src
parent6e1571533fd92bec67e5ab9b1dd1e15032925757 (diff)
parent40da501d8989913935660dc24953ece02c9e98b8 (diff)
downloadqemu-master.zip
qemu-master.tar.gz
qemu-master.tar.bz2
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into stagingHEADstagingmaster
* cleanups for distributed DTB files * scripts/meson-buildoptions: Sort coroutine_backend choices lexicographically * rust/qemu-api: Add initial logging support : rust: pl011: Implement logging * target/i386: fix Win98 * meson: cleanup win32 library detection * rust: safe(r) instance_init * rust: prepare for multiple bindgen invocations * rust: fix new warning * target/i386: Warn about why CPUID_EXT_PDCM is not available * target/i386: small TDX fixes and clarifications * target/i386: support for TDX quote generation # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCgAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmhVRWsUHHBib256aW5p # QHJlZGhhdC5jb20ACgkQv/vSX3jHroOyDQf/YqX2jTZbC4jXdHZT6YiDlYPX9MPx # emFX0S+30X5zNuGYUQufKHEJWshMtklB1seUTQathOPaNeCFK13lY4m1CRbhbrMs # 3iG4ZQf5V+YTuB+JuE8KfclJeAPXDTnIc2uJbtXErIsPBeEGYZelFLnO5HLiMsY3 # iX9S2hSkjvjlikFv/m9ebg9SMP3+/ZunQMZxsDwgb7U3uqtuZagCJTWz0xTHHHxV # Ko5OPA0kIydm0NnlHs2DsF1mivmYSSIfBnxg4KXgmJxd3gNGd9SemBQOwYU68x0T # R3GzI6NLgdP/3mKOsxpM6hFiXBp84eT6zghpdqK5zQFidgz935EXP5WjvQ== # =ttQr # -----END PGP SIGNATURE----- # gpg: Signature made Fri 20 Jun 2025 07:26:35 EDT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: (24 commits) i386/tdx: handle TDG.VP.VMCALL<GetQuote> i386/tdx: handle TDG.VP.VMCALL<GetTdVmCallInfo> update Linux headers to v6.16-rc3 i386/tdx: Clarify the error message of mrconfigid/mrowner/mrownerconfig i386/tdx: Fix the typo of the comment of struct TdxGuest i386/cpu: Rename enable_cpuid_0x1f to force_cpuid_0x1f i386/tdx: Error and exit when named cpu model is requested i386/cpu: Warn about why CPUID_EXT_PDCM is not available i386/cpu: Move adjustment of CPUID_EXT_PDCM before feature_dependencies[] check rust: hpet: fix new warning rust: pl011: Add missing logging to match C version rust: pl011: Implement logging rust/qemu-api: Add initial logging support based on C API rust: move rust.bindgen to qemu-api crate rust: prepare variable definitions for multiple bindgen invocations rust: qom: change instance_init to take a ParentInit<> rust: qom: make ParentInit lifetime-invariant rust: qom: introduce ParentInit rust: hpet: fully initialize object during instance_init rust: qemu_api: introduce MaybeUninit field projection ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'rust/hw/timer/hpet/src')
-rw-r--r--rust/hw/timer/hpet/src/device.rs58
1 files changed, 31 insertions, 27 deletions
diff --git a/rust/hw/timer/hpet/src/device.rs b/rust/hw/timer/hpet/src/device.rs
index 735b2fb..acf7251 100644
--- a/rust/hw/timer/hpet/src/device.rs
+++ b/rust/hw/timer/hpet/src/device.rs
@@ -4,6 +4,7 @@
use std::{
ffi::{c_int, c_void, CStr},
+ mem::MaybeUninit,
pin::Pin,
ptr::{addr_of_mut, null_mut, NonNull},
slice::from_ref,
@@ -20,11 +21,12 @@ use qemu_api::{
hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder, MEMTXATTRS_UNSPECIFIED,
},
prelude::*,
- qdev::{DeviceImpl, DeviceMethods, DeviceState, Property, ResetType, ResettablePhasesImpl},
- qom::{ObjectImpl, ObjectType, ParentField},
+ qdev::{DeviceImpl, DeviceState, Property, ResetType, ResettablePhasesImpl},
+ qom::{ObjectImpl, ObjectType, ParentField, ParentInit},
qom_isa,
sysbus::{SysBusDevice, SysBusDeviceImpl},
timer::{Timer, CLOCK_VIRTUAL, NANOSECONDS_PER_SECOND},
+ uninit_field_mut,
vmstate::VMStateDescription,
vmstate_fields, vmstate_of, vmstate_struct, vmstate_subsections, vmstate_validate,
zeroable::Zeroable,
@@ -212,13 +214,13 @@ pub struct HPETTimer {
}
impl HPETTimer {
- fn init(&mut self, index: u8, state: &HPETState) {
- *self = HPETTimer {
+ fn new(index: u8, state: *const HPETState) -> HPETTimer {
+ HPETTimer {
index,
// SAFETY: the HPETTimer will only be used after the timer
// is initialized below.
qemu_timer: unsafe { Timer::new() },
- state: NonNull::new((state as *const HPETState).cast_mut()).unwrap(),
+ state: NonNull::new(state.cast_mut()).unwrap(),
config: 0,
cmp: 0,
fsb: 0,
@@ -226,19 +228,15 @@ impl HPETTimer {
period: 0,
wrap_flag: 0,
last: 0,
- };
+ }
+ }
+ fn init_timer_with_cell(cell: &BqlRefCell<Self>) {
+ let mut timer = cell.borrow_mut();
// SAFETY: HPETTimer is only used as part of HPETState, which is
// always pinned.
- let qemu_timer = unsafe { Pin::new_unchecked(&mut self.qemu_timer) };
- qemu_timer.init_full(
- None,
- CLOCK_VIRTUAL,
- Timer::NS,
- 0,
- timer_handler,
- &state.timers[self.index as usize],
- )
+ let qemu_timer = unsafe { Pin::new_unchecked(&mut timer.qemu_timer) };
+ qemu_timer.init_full(None, CLOCK_VIRTUAL, Timer::NS, 0, timer_handler, cell);
}
fn get_state(&self) -> &HPETState {
@@ -607,9 +605,18 @@ impl HPETState {
}
}
- fn init_timer(&self) {
- for (index, timer) in self.timers.iter().enumerate() {
- timer.borrow_mut().init(index.try_into().unwrap(), self);
+ fn init_timers(this: &mut MaybeUninit<Self>) {
+ let state = this.as_ptr();
+ for index in 0..HPET_MAX_TIMERS {
+ let mut timer = uninit_field_mut!(*this, timers[index]);
+
+ // Initialize in two steps, to avoid calling Timer::init_full on a
+ // temporary that can be moved.
+ let timer = timer.write(BqlRefCell::new(HPETTimer::new(
+ index.try_into().unwrap(),
+ state,
+ )));
+ HPETTimer::init_timer_with_cell(timer);
}
}
@@ -690,7 +697,7 @@ impl HPETState {
.set(self.counter.get().deposit(shift, len, val));
}
- unsafe fn init(&mut self) {
+ unsafe fn init(mut this: ParentInit<Self>) {
static HPET_RAM_OPS: MemoryRegionOps<HPETState> =
MemoryRegionOpsBuilder::<HPETState>::new()
.read(&HPETState::read)
@@ -700,16 +707,14 @@ impl HPETState {
.impl_sizes(4, 8)
.build();
- // SAFETY:
- // self and self.iomem are guaranteed to be valid at this point since callers
- // must make sure the `self` reference is valid.
MemoryRegion::init_io(
- unsafe { &mut *addr_of_mut!(self.iomem) },
- addr_of_mut!(*self),
+ &mut uninit_field_mut!(*this, iomem),
&HPET_RAM_OPS,
"hpet",
HPET_REG_SPACE_LEN,
);
+
+ Self::init_timers(&mut this);
}
fn post_init(&self) {
@@ -731,7 +736,6 @@ impl HPETState {
self.hpet_id.set(HPETFwConfig::assign_hpet_id()?);
- self.init_timer();
// 64-bit General Capabilities and ID Register; LegacyReplacementRoute.
self.capability.set(
HPET_CAP_REV_ID_VALUE << HPET_CAP_REV_ID_SHIFT |
@@ -767,7 +771,7 @@ impl HPETState {
self.rtc_irq_level.set(0);
}
- fn decode(&self, mut addr: hwaddr, size: u32) -> HPETAddrDecode {
+ fn decode(&self, mut addr: hwaddr, size: u32) -> HPETAddrDecode<'_> {
let shift = ((addr & 4) * 8) as u32;
let len = std::cmp::min(size * 8, 64 - shift);
@@ -892,7 +896,7 @@ unsafe impl ObjectType for HPETState {
impl ObjectImpl for HPETState {
type ParentType = SysBusDevice;
- const INSTANCE_INIT: Option<unsafe fn(&mut Self)> = Some(Self::init);
+ const INSTANCE_INIT: Option<unsafe fn(ParentInit<Self>)> = Some(Self::init);
const INSTANCE_POST_INIT: Option<fn(&Self)> = Some(Self::post_init);
const CLASS_INIT: fn(&mut Self::Class) = Self::Class::class_init::<Self>;
}