From nobody Sun Dec 14 06:42:49 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1763369322; cv=none; d=zohomail.com; s=zohoarc; b=NIlzhzLrf0qdhefD/qv7/7NGGPn53MwZ6jd6zzdBrg36xGE+/+wxZZQ7f6R1WGtbJi+L7DOLMOhxwBfzc/5mKFeQQUswjln485mMHFCjyxISA0nAUcDEtPFoetKne1CInkbLDUPiCIhrKJHPn3Z5fdFr7+OnbLJAJ7wOn1rNZpc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1763369322; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Cn7Y8H+ZHnVPbLSpcflMd4rMa6WaX6x5Zv7H11YwVEk=; b=SL7yjRktKM54TLWPPTQOfus+UtlJwdTGKmosvvi5QmRr/VlLeBCCsofy0i87OCCu98u1dyQAZ1sIAwarLIueTjLmvXvzoexExSAn4rERTDpp2aJ1TqUk0GqNPOpUE+ByEShGmxZMkp72xS2DZ+j/OzOlwGGcsBBJmrLgVF2GB4g= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1763369322259916.5401358589513; Mon, 17 Nov 2025 00:48:42 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vKuuH-0004GZ-0e; Mon, 17 Nov 2025 03:48:17 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vKuu6-000422-W4 for qemu-devel@nongnu.org; Mon, 17 Nov 2025 03:48:08 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vKuu4-000711-5T for qemu-devel@nongnu.org; Mon, 17 Nov 2025 03:48:06 -0500 Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-166-X_Qmuh4BODmIIiD_J3UylA-1; Mon, 17 Nov 2025 03:48:01 -0500 Received: by mail-wm1-f70.google.com with SMTP id 5b1f17b1804b1-477a60a23adso2158375e9.2 for ; Mon, 17 Nov 2025 00:48:00 -0800 (PST) Received: from [192.168.10.48] ([176.206.119.13]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4779973ddcfsm119750635e9.15.2025.11.17.00.47.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Nov 2025 00:47:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1763369282; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Cn7Y8H+ZHnVPbLSpcflMd4rMa6WaX6x5Zv7H11YwVEk=; b=I+CpiBKR2Z489BxIUsISBiGJYluuNLwb3X/UjUp8w7u4Jq0Nr3AKRxx41Uw6OZXyQMFI9N 3lqPJyV7wxhJlcW4sflanL+ut8OAe3DPjcxU5VM0tv9Vij4Od9IUuWVUx9ifcs0HPvECjk 4jesdbrWfsPhVBBHjr+kox3GKdO9KPs= X-MC-Unique: X_Qmuh4BODmIIiD_J3UylA-1 X-Mimecast-MFC-AGG-ID: X_Qmuh4BODmIIiD_J3UylA_1763369280 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1763369279; x=1763974079; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Cn7Y8H+ZHnVPbLSpcflMd4rMa6WaX6x5Zv7H11YwVEk=; b=XyTF0PjVqXA0s1FRgdui6ghIS8GXPlSaL0IR22sntPU/BQffmmCm8xQLlfyQ4aoFGS gPaAViBt/WRzbpPHq48wCEWY8f1Z6YA7/ffS9NiwxWtQEkmOLs+LZVaIUxvVgO7Qii2m 5yJlrcet4w0QkNMmLIhLgNz9QnuVyM6BfP/rQT2DHmZl6UwcPN/Rx0AOOwiU3FEO24cr EbPUe0YVy4ikqCoiGFqWE1KX6/EoslwCVzspfuTNZ+1VxYdamDDKQt7lXYxD9/3Ue1S0 7E7Yjvh5qvECIGNv1jVXDcLJ+963NKRbBzW4xSS9cWh9/3OJ6pcexsDHS9z7uL/uNHpf Vz9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763369279; x=1763974079; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Cn7Y8H+ZHnVPbLSpcflMd4rMa6WaX6x5Zv7H11YwVEk=; b=pnhD507X5vYIXexOhLHG4MoKcCnZzSFcKTBU9Bz7YQF61xJWiM6in/PG643E8Y+xQp tUTrpEjwmr2K6A3+QwZvzEzWDR4YddghHyTsWoGZb3eSvgbzD40PDhs18QijV55vkdfd ta3qFDcFQAHuOIAV25kA26x0idOuUiyvmCk+fkqOAlAXyOymYAwySypMo4W91R0alg6F dNduiTMHVH9WiCEpswh7q1bSoh3Rokr+v2FNOp4eH1KH6RuUrFYsy05IfC9ea13Zgtsz eXnQdTjSMHGPciO54Qrdx/WaeM+av7CZ8us9623qwyHZu32ATYkDKxUB3fRUHZlTLZCy bUXQ== X-Gm-Message-State: AOJu0YxIoNf//IpHFUEZI8lkPGReSt/iRH79+3gSmllTVEhFr5QIUhfU mI5Y8kW0CAIA3yth6m0+UDZ0vu9wymswbcFIKRgT1JWxD0JZD1ZvGjX/DzK6XRoL5p0A6+YF895 5/gRGtXWKcZE9rIFP5YQ44UZ7LZXDrHxsH9s3Me32YJBFTjRjj7OW+giUpXM+pM3g2WNP1zNzTZ U8xakcv9Ssq3/KB2w8ycwXwtTHwDhWw28odh225fx9 X-Gm-Gg: ASbGncsdtdXvJafBeJEIPcIWT67+WJiZzcQgAqXtn2XFa+maGx2pj5bSw7jCmJBCbnT 5kdP+vxiSDt/cbklYEtnQ0d32R7ewE3/y+LTY+U99CNzP8F5BQGJYlV/MI+bAR4XA2zTwIkJddA PnLuNpI3cPZza5vpYmTUxRZQKGm2SWizv7v0PYlpHqRPHeOqpB4fIKc/nUfs2FELB2P4AS0DDp/ vukGhLJOfZnaVBh6Td09+nVD5V5P1gS1CqdVcfp8IEA8zbXumIB7Fqk+H6MlbTRWhBTSBaHzXJ/ tLtYLrjY1qP2aIQ2h30sTQDqYC7y3pnXNJEPW//Jiw3hHZv3wZRf22uwKfYu9ydOnJD5C0FcHUe PeJGvpA3yiOs52Usf487QCt1BX4lpOkmNR45cebdTfW4Vr9LMPFxxo33TaejxI3kAUjaMDsDqKk yJCPDg X-Received: by 2002:a05:600c:1382:b0:477:3e0b:c0e3 with SMTP id 5b1f17b1804b1-4778fea1743mr106795285e9.32.1763369278617; Mon, 17 Nov 2025 00:47:58 -0800 (PST) X-Google-Smtp-Source: AGHT+IFprj2baOOhEB6xEp2DyXI+sJu+pBju1TU/tDTs3euXo6dskJazIaHO3PDmEB0fYo56Q36GAg== X-Received: by 2002:a05:600c:1382:b0:477:3e0b:c0e3 with SMTP id 5b1f17b1804b1-4778fea1743mr106794855e9.32.1763369277945; Mon, 17 Nov 2025 00:47:57 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, zhao1.liu@intel.com Subject: [PATCH 1/5] rust/hpet: move hidden registers to HPETTimerRegisters Date: Mon, 17 Nov 2025 09:47:48 +0100 Message-ID: <20251117084752.203219-2-pbonzini@redhat.com> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251117084752.203219-1-pbonzini@redhat.com> References: <20251117084752.203219-1-pbonzini@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1763369325041153000 Content-Type: text/plain; charset="utf-8" Do not separate visible and hidden state; both of them are used in the same circumstances and it's easiest to place both of them under the same BqlRefCell. Signed-off-by: Paolo Bonzini Reviewed-by: Zhao Liu --- rust/hw/timer/hpet/src/device.rs | 157 ++++++++++++++----------------- 1 file changed, 71 insertions(+), 86 deletions(-) diff --git a/rust/hw/timer/hpet/src/device.rs b/rust/hw/timer/hpet/src/devi= ce.rs index a1deef5a467..79d818b43da 100644 --- a/rust/hw/timer/hpet/src/device.rs +++ b/rust/hw/timer/hpet/src/device.rs @@ -171,9 +171,9 @@ const fn deactivating_bit(old: u64, new: u64, shift: us= ize) -> bool { } =20 fn timer_handler(timer_cell: &BqlRefCell) { - let mut t =3D timer_cell.borrow_mut(); + let t =3D timer_cell.borrow(); // SFAETY: state field is valid after timer initialization. - let regs =3D &mut unsafe { t.state.as_mut() }.regs.borrow_mut(); + let regs =3D &mut unsafe { t.state.as_ref() }.regs.borrow_mut(); t.callback(regs) } =20 @@ -187,9 +187,35 @@ pub struct HPETTimerRegisters { cmp: u64, /// Timer N FSB Interrupt Route Register fsb: u64, + + // Hidden register state + /// comparator (extended to counter width) + cmp64: u64, + /// Last value written to comparator + period: u64, + /// timer pop will indicate wrap for one-shot 32-bit + /// mode. Next pop will be actual timer expiration. + wrap_flag: u8, + /// last value armed, to avoid timer storms + last: u64, } =20 impl HPETTimerRegisters { + /// calculate next value of the general counter that matches the + /// target (either entirely, or the low 32-bit only depending on + /// the timer mode). + fn update_cmp64(&mut self, cur_tick: u64) { + self.cmp64 =3D if self.is_32bit_mod() { + let mut result: u64 =3D cur_tick.deposit(0, 32, self.cmp); + if result < cur_tick { + result +=3D 0x100000000; + } + result + } else { + self.cmp + } + } + const fn is_fsb_route_enabled(&self) -> bool { self.config & (1 << HPET_TN_CFG_FSB_ENABLE_SHIFT) !=3D 0 } @@ -234,17 +260,6 @@ pub struct HPETTimer { qemu_timer: Timer, /// timer block abstraction containing this timer state: NonNull, - - // Hidden register state - /// comparator (extended to counter width) - cmp64: u64, - /// Last value written to comparator - period: u64, - /// timer pop will indicate wrap for one-shot 32-bit - /// mode. Next pop will be actual timer expiration. - wrap_flag: u8, - /// last value armed, to avoid timer storms - last: u64, } =20 // SAFETY: Sync is not automatically derived due to the `state` field, @@ -259,10 +274,6 @@ fn new(index: u8, state: *const HPETState) -> HPETTime= r { // is initialized below. qemu_timer: unsafe { Timer::new() }, state: NonNull::new(state.cast_mut()).unwrap(), - cmp64: 0, - period: 0, - wrap_flag: 0, - last: 0, } } =20 @@ -290,28 +301,6 @@ fn is_int_active(&self, regs: &HPETRegisters) -> bool { regs.is_timer_int_active(self.index.into()) } =20 - /// calculate next value of the general counter that matches the - /// target (either entirely, or the low 32-bit only depending on - /// the timer mode). - fn calculate_cmp64(&self, regs: &HPETRegisters, cur_tick: u64, target:= u64) -> u64 { - // &HPETRegisters should be gotten from BqlRefCell, - // but there's no lock guard to guarantee this. So we have to chec= k BQL - // context explicitly. This check should be removed when we switch= to - // Mutex. - assert!(bql::is_locked()); - - let tn_regs =3D ®s.tn_regs[self.index as usize]; - if tn_regs.is_32bit_mod() { - let mut result: u64 =3D cur_tick.deposit(0, 32, target); - if result < cur_tick { - result +=3D 0x100000000; - } - result - } else { - target - } - } - fn get_int_route(&self, regs: &HPETRegisters) -> usize { // &HPETRegisters should be gotten from BqlRefCell, // but there's no lock guard to guarantee this. So we have to chec= k BQL @@ -394,47 +383,46 @@ fn update_irq(&self, regs: &mut HPETRegisters, set: b= ool) { self.set_irq(regs, set); } =20 - fn arm_timer(&mut self, regs: &HPETRegisters, tick: u64) { + fn arm_timer(&self, tn_regs: &mut HPETTimerRegisters, tick: u64) { // &HPETRegisters should be gotten from BqlRefCell, // but there's no lock guard to guarantee this. So we have to chec= k BQL // context explicitly. This check should be removed when we switch= to // Mutex. assert!(bql::is_locked()); =20 - let tn_regs =3D ®s.tn_regs[self.index as usize]; let mut ns =3D self.get_state().get_ns(tick); =20 // Clamp period to reasonable min value (1 us) - if tn_regs.is_periodic() && ns - self.last < 1000 { - ns =3D self.last + 1000; + if tn_regs.is_periodic() && ns - tn_regs.last < 1000 { + ns =3D tn_regs.last + 1000; } =20 - self.last =3D ns; - self.qemu_timer.modify(self.last); + tn_regs.last =3D ns; + self.qemu_timer.modify(tn_regs.last); } =20 - fn set_timer(&mut self, regs: &HPETRegisters) { + fn set_timer(&self, regs: &mut HPETRegisters) { // &HPETRegisters should be gotten from BqlRefCell, // but there's no lock guard to guarantee this. So we have to chec= k BQL // context explicitly. This check should be removed when we switch= to // Mutex. assert!(bql::is_locked()); =20 - let tn_regs =3D ®s.tn_regs[self.index as usize]; + let tn_regs =3D &mut regs.tn_regs[self.index as usize]; let cur_tick: u64 =3D self.get_state().get_ticks(); =20 - self.wrap_flag =3D 0; - self.cmp64 =3D self.calculate_cmp64(regs, cur_tick, tn_regs.cmp); + tn_regs.wrap_flag =3D 0; + tn_regs.update_cmp64(cur_tick); if tn_regs.is_32bit_mod() { // HPET spec says in one-shot 32-bit mode, generate an interru= pt when // counter wraps in addition to an interrupt with comparator m= atch. - if !tn_regs.is_periodic() && self.cmp64 > hpet_next_wrap(cur_t= ick) { - self.wrap_flag =3D 1; - self.arm_timer(regs, hpet_next_wrap(cur_tick)); + if !tn_regs.is_periodic() && tn_regs.cmp64 > hpet_next_wrap(cu= r_tick) { + tn_regs.wrap_flag =3D 1; + self.arm_timer(tn_regs, hpet_next_wrap(cur_tick)); return; } } - self.arm_timer(regs, self.cmp64); + self.arm_timer(tn_regs, tn_regs.cmp64); } =20 fn del_timer(&self, regs: &mut HPETRegisters) { @@ -485,7 +473,7 @@ fn prepare_tn_cfg_reg_new( } =20 /// Configuration and Capability Register - fn set_tn_cfg_reg(&mut self, regs: &mut HPETRegisters, shift: u32, len= : u32, val: u64) { + fn set_tn_cfg_reg(&self, regs: &mut HPETRegisters, shift: u32, len: u3= 2, val: u64) { // &mut HPETRegisters should be gotten from BqlRefCell, // but there's no lock guard to guarantee this. So we have to chec= k BQL // context explicitly. This check should be removed when we switch= to @@ -508,7 +496,7 @@ fn set_tn_cfg_reg(&mut self, regs: &mut HPETRegisters, = shift: u32, len: u32, val let tn_regs =3D &mut regs.tn_regs[self.index as usize]; if tn_regs.is_32bit_mod() { tn_regs.cmp =3D u64::from(tn_regs.cmp as u32); // truncate! - self.period =3D u64::from(self.period as u32); // truncate! + tn_regs.period =3D u64::from(tn_regs.period as u32); // trunca= te! } =20 if regs.is_hpet_enabled() { @@ -517,7 +505,7 @@ fn set_tn_cfg_reg(&mut self, regs: &mut HPETRegisters, = shift: u32, len: u32, val } =20 /// Comparator Value Register - fn set_tn_cmp_reg(&mut self, regs: &mut HPETRegisters, shift: u32, len= : u32, val: u64) { + fn set_tn_cmp_reg(&self, regs: &mut HPETRegisters, shift: u32, len: u3= 2, val: u64) { // &mut HPETRegisters should be gotten from BqlRefCell, // but there's no lock guard to guarantee this. So we have to chec= k BQL // context explicitly. This check should be removed when we switch= to @@ -545,7 +533,7 @@ fn set_tn_cmp_reg(&mut self, regs: &mut HPETRegisters, = shift: u32, len: u32, val } =20 if tn_regs.is_periodic() { - self.period =3D self.period.deposit(shift, length, value); + tn_regs.period =3D tn_regs.period.deposit(shift, length, value= ); } =20 tn_regs.clear_valset(); @@ -566,7 +554,7 @@ fn set_tn_fsb_route_reg(&self, regs: &mut HPETRegisters= , shift: u32, len: u32, v tn_regs.fsb =3D tn_regs.fsb.deposit(shift, len, val); } =20 - fn reset(&mut self, regs: &mut HPETRegisters) { + fn reset(&self, regs: &mut HPETRegisters) { // &mut HPETRegisters should be gotten from BqlRefCell, // but there's no lock guard to guarantee this. So we have to chec= k BQL // context explicitly. This check should be removed when we switch= to @@ -584,12 +572,12 @@ fn reset(&mut self, regs: &mut HPETRegisters) { // advertise availability of ioapic int tn_regs.config |=3D (u64::from(self.get_state().int_route_cap)) << HPET_TN_CFG_INT= _ROUTE_CAP_SHIFT; - self.period =3D 0; - self.wrap_flag =3D 0; + tn_regs.period =3D 0; + tn_regs.wrap_flag =3D 0; } =20 /// timer expiration callback - fn callback(&mut self, regs: &mut HPETRegisters) { + fn callback(&self, regs: &mut HPETRegisters) { // &mut HPETRegisters should be gotten from BqlRefCell, // but there's no lock guard to guarantee this. So we have to chec= k BQL // context explicitly. This check should be removed when we switch= to @@ -597,22 +585,21 @@ fn callback(&mut self, regs: &mut HPETRegisters) { assert!(bql::is_locked()); =20 let tn_regs =3D &mut regs.tn_regs[self.index as usize]; - let period: u64 =3D self.period; let cur_tick: u64 =3D self.get_state().get_ticks(); =20 - if tn_regs.is_periodic() && period !=3D 0 { - while hpet_time_after(cur_tick, self.cmp64) { - self.cmp64 +=3D period; + if tn_regs.is_periodic() && tn_regs.period !=3D 0 { + while hpet_time_after(cur_tick, tn_regs.cmp64) { + tn_regs.cmp64 +=3D tn_regs.period; } if tn_regs.is_32bit_mod() { - tn_regs.cmp =3D u64::from(self.cmp64 as u32); // truncate! + tn_regs.cmp =3D u64::from(tn_regs.cmp64 as u32); // trunca= te! } else { - tn_regs.cmp =3D self.cmp64; + tn_regs.cmp =3D tn_regs.cmp64; } - self.arm_timer(regs, self.cmp64); - } else if self.wrap_flag !=3D 0 { - self.wrap_flag =3D 0; - self.arm_timer(regs, self.cmp64); + self.arm_timer(tn_regs, tn_regs.cmp64); + } else if tn_regs.wrap_flag !=3D 0 { + tn_regs.wrap_flag =3D 0; + self.arm_timer(tn_regs, tn_regs.cmp64); } self.update_irq(regs, true); } @@ -635,7 +622,7 @@ fn read(&self, target: TimerRegister, regs: &HPETRegist= ers) -> u64 { } =20 fn write( - &mut self, + &self, target: TimerRegister, regs: &mut HPETRegisters, value: u64, @@ -796,7 +783,7 @@ fn set_cfg_reg(&self, regs: &mut HPETRegisters, shift: = u32, len: u32, val: u64) .set(ticks_to_ns(regs.counter) - CLOCK_VIRTUAL.get_ns()); =20 for timer in self.timers.iter().take(self.num_timers) { - let mut t =3D timer.borrow_mut(); + let t =3D timer.borrow(); let id =3D t.index as usize; let tn_regs =3D ®s.tn_regs[id]; =20 @@ -937,7 +924,7 @@ fn reset_hold(&self, _type: ResetType) { let mut regs =3D self.regs.borrow_mut(); =20 for timer in self.timers.iter().take(self.num_timers) { - timer.borrow_mut().reset(&mut regs); + timer.borrow().reset(&mut regs); } =20 regs.counter =3D 0; @@ -989,7 +976,7 @@ fn read(&self, addr: hwaddr, size: u32) -> u64 { use DecodedRegister::*; use GlobalRegister::*; (match target { - Timer(timer, tn_target) =3D> timer.borrow_mut().read(tn_target= , regs), + Timer(timer, tn_target) =3D> timer.borrow().read(tn_target, re= gs), Global(CAP) =3D> regs.capability, /* including HPET_PERIOD 0x0= 04 */ Global(CFG) =3D> regs.config, Global(INT_STATUS) =3D> regs.int_status, @@ -1020,7 +1007,7 @@ fn write(&self, addr: hwaddr, value: u64, size: u32) { use DecodedRegister::*; use GlobalRegister::*; match target { - Timer(timer, tn_target) =3D> timer.borrow_mut().write(tn_targe= t, regs, value, shift, len), + Timer(timer, tn_target) =3D> timer.borrow().write(tn_target, r= egs, value, shift, len), Global(CAP) =3D> {} // General Capabilities and ID Register: R= ead Only Global(CFG) =3D> self.set_cfg_reg(regs, shift, len, value), Global(INT_STATUS) =3D> self.set_int_status_reg(regs, shift, l= en, value), @@ -1045,15 +1032,14 @@ fn pre_save(&self) -> Result<(), migration::Infalli= ble> { } =20 fn post_load(&self, _version_id: u8) -> Result<(), migration::Infallib= le> { - let regs =3D self.regs.borrow(); + let mut regs =3D self.regs.borrow_mut(); + let cnt =3D regs.counter; =20 - for timer in self.timers.iter().take(self.num_timers) { - let mut t =3D timer.borrow_mut(); - let cnt =3D regs.counter; - let cmp =3D regs.tn_regs[t.index as usize].cmp; + for index in 0..self.num_timers { + let tn_regs =3D &mut regs.tn_regs[index]; =20 - t.cmp64 =3D t.calculate_cmp64(®s, cnt, cmp); - t.last =3D CLOCK_VIRTUAL.get_ns() - NANOSECONDS_PER_SECOND; + tn_regs.update_cmp64(cnt); + tn_regs.last =3D CLOCK_VIRTUAL.get_ns() - NANOSECONDS_PER_SECO= ND; } =20 // Recalculate the offset between the main counter and guest time @@ -1126,6 +1112,8 @@ impl ObjectImpl for HPETState { vmstate_of!(HPETTimerRegisters, config), vmstate_of!(HPETTimerRegisters, cmp), vmstate_of!(HPETTimerRegisters, fsb), + vmstate_of!(HPETTimerRegisters, period), + vmstate_of!(HPETTimerRegisters, wrap_flag), }) .build() ); @@ -1136,9 +1124,6 @@ impl ObjectImpl for HPETState { .version_id(2) .minimum_version_id(2) .fields(vmstate_fields! { - vmstate_of!(HPETTimer, index), - vmstate_of!(HPETTimer, period), - vmstate_of!(HPETTimer, wrap_flag), vmstate_of!(HPETTimer, qemu_timer), }) .build(); --=20 2.51.1 From nobody Sun Dec 14 06:42:49 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1763369369; cv=none; d=zohomail.com; s=zohoarc; b=dZ0O7TJoBvmD3D438ZGRZ+jPmLQ6jLSw8OH/I3kcOJpPWxQ4uYqFW/doGzc5CsO/eDTpeGiT0UmNNGFafxkd/2Mn1jVjZFTsmWnWS1SscFpVpCZSGQPHiqpQ2SPtAZytSFFoK3sZdA5sLfLyE4M8BsyHlTZxz+gchY1IjqFCW/g= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1763369369; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=hmfGcUcX6SbGzzDYoFBngcqcgk8heYgOyWXNHnYO7GU=; b=Uu6/QWn9JnzP33RgfeFbqWwqVzUIHjtglpqKEKgUSJ1/+neMmJpwu6L71QgZ7+vm40gCePXnkMwvRMsciZywFWflW2TiRIUdmrKqcchRXpcTYJ6xH3lEPS/YF6pYPNZzepmWa09AdIM8mXmX1HBQ/2tHNk63rcZfeUxZ4myeZW4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1763369369367188.54585315450902; Mon, 17 Nov 2025 00:49:29 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vKuuC-00046Q-Ab; Mon, 17 Nov 2025 03:48:12 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vKuu9-00044C-Hz for qemu-devel@nongnu.org; Mon, 17 Nov 2025 03:48:11 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vKuu7-00071R-EZ for qemu-devel@nongnu.org; Mon, 17 Nov 2025 03:48:08 -0500 Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-197-3s7R7A5UMEyfyf8v_PWCQw-1; Mon, 17 Nov 2025 03:48:03 -0500 Received: by mail-wm1-f70.google.com with SMTP id 5b1f17b1804b1-4779b3749a8so10531365e9.1 for ; Mon, 17 Nov 2025 00:48:03 -0800 (PST) Received: from [192.168.10.48] ([176.206.119.13]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4779fab9b0esm76902095e9.12.2025.11.17.00.47.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Nov 2025 00:47:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1763369286; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hmfGcUcX6SbGzzDYoFBngcqcgk8heYgOyWXNHnYO7GU=; b=BWaLFOKPZpgHIdpJuJTri8hkCf9dRJXEyE3YV6fE53BE9UmNZ/GOWEhqJKGsUrjNrCde8L UFlIr+7ONmCu+MQeag91dfbEwCeB5WG0qAPRwiKh2lSdUgvdL2MeV5lVO9UOXTdJ3Qakwf aSWtCS1EJ/tDK6gtkk5FTDBbAxnvUss= X-MC-Unique: 3s7R7A5UMEyfyf8v_PWCQw-1 X-Mimecast-MFC-AGG-ID: 3s7R7A5UMEyfyf8v_PWCQw_1763369282 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1763369281; x=1763974081; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=hmfGcUcX6SbGzzDYoFBngcqcgk8heYgOyWXNHnYO7GU=; b=n26Lq/6jdb86iWC/lXlYXi+YS845dGzCqpV4wbF7q6MSKRUm6XoCgTvUrGTlwV0m3M eAKZTWV6B1XpvpVMQtqO/hgyu3ceXYSPbWZRlqSlY13pnZ/D4V2AMpbrHUHxpdvR6Zuh IRhOx3Ye7/FInSOKRsL1PmNdg6LKtBDTJyDwtaoyqDIFIQOsx2KQpw+Vm4+W6LtUjlda 9qWVnZvRbmcZaHmK9mE3Nuc05MJWaD6QsSIZU9Svj890tXQ+qU++aZ2c4Yyqg/Xxtw5R EOdVWsb9FAJzO+CtmT+BChrW46JNYkPRzjiRX7Jd4idaaZEofUnWxdqtFLQKIzuYDFkn +E5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763369281; x=1763974081; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=hmfGcUcX6SbGzzDYoFBngcqcgk8heYgOyWXNHnYO7GU=; b=a65jP2bRqEQVJ4JGSbmPepT+qJHJgv7NoP9xQfcCDB4QYIqT5k0LjK17r7cAzRfJx3 dyKkJ/8eLQLMd6b3es5Ktfyvo0YYnyPbLeV8iW/nxBW5WxVIqvzUUJOnrJsc0Oxp1/F2 +9urimTY7I53yiP+uVGYhcjatgCVGkhxe+OaHlhQemkOi692U5olLSG4jBbdksaamyAd Fb6llriU6YhOlBOWtniBmf+/d+d6+kzTEmu5RH4jQln58CiTGsWRFr/276cK7B9kzXZJ Ff6Xt5kX/iv9eOLpvq7GhyIVlVKab1LneBxM79hKcX1ERf9XfJba2kr6CG0g9WRiet2K WUVA== X-Gm-Message-State: AOJu0YzXTw0saIA5ZX4VtFMsETAvtBUIgLFMt4JKK+6A/74c+ThFza4M g3y+/6Duf7ROSrBcE8cjEZmJxfbWbV1xE/g18KKHSQgeL+wPv+XQAJLVj31l6oodU9mj/HKLw7b btlZHdnP0ONN/Cvz6fcL0H7cLq2zPcBjCRchKzWruSneXTa1bcq5WB1C/BxCgLS+4tqJMqoLaaN Dd6mfXxh9sgeFejTD3LB+tU0Z2z/JKXxQ7yA7W4aU/ X-Gm-Gg: ASbGnct//g7veYGHhHJKLSphQfqb6kMg6d8giY6//d4g+4kGJeoXE5kSNeMqcMy0MJn WjFgLkrkE1Ohow6b06MI+fbX95U3+WUfK4CRbpwOYY9V3EWpcDy6Hvh0tPZjHdeymLngz9LUV5N XQuHOeIReDrOCEvIr04L06/eZLR/zRoygMUFX/wt4nBEvI4du5g1jUOnXyPet58JYovz+I7xIIe WQBNvx51oMAnCiTXoHPGmSmz9ytbuCsXs6U0Z3hqpL3yse6K6AWtkncUnOzUKBuDVQqHgw1u6GY OKidYWtFQOLlnkQstUNklJaD7JKtJ1X12D9IcRkCIxR6MiR4XF0qorxchsB16adxSTwBQW/JOhQ DHsECoMouda2sUeHBUzOUEahAOt1Kyu756o+E6fiaIMj02f5vSaL4Fv+nY6U5h7Yvmf8KQrX16E ZSTQEu X-Received: by 2002:a05:600c:8b4c:b0:477:7f4a:44ba with SMTP id 5b1f17b1804b1-4778fe60072mr91365475e9.4.1763369281484; Mon, 17 Nov 2025 00:48:01 -0800 (PST) X-Google-Smtp-Source: AGHT+IH4RnIczh/+SFD3CcfUVb3uKUYsCASYYfuBGZiETyuF4yws/fukm0fcfrZaWn8D0q4lwww3MA== X-Received: by 2002:a05:600c:8b4c:b0:477:7f4a:44ba with SMTP id 5b1f17b1804b1-4778fe60072mr91365105e9.4.1763369280698; Mon, 17 Nov 2025 00:48:00 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, zhao1.liu@intel.com Subject: [PATCH 2/5] rust/hpet: move hpet_offset to HPETRegisters Date: Mon, 17 Nov 2025 09:47:49 +0100 Message-ID: <20251117084752.203219-3-pbonzini@redhat.com> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251117084752.203219-1-pbonzini@redhat.com> References: <20251117084752.203219-1-pbonzini@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1763369372693158500 Content-Type: text/plain; charset="utf-8" Likewise, do not separate hpet_offset from the other registers. However, because it is migrated in a subsection it is necessary to copy it out of HPETRegisters and into a BqlCell<>. Signed-off-by: Paolo Bonzini Reviewed-by: Zhao Liu --- rust/hw/timer/hpet/src/device.rs | 63 ++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/rust/hw/timer/hpet/src/device.rs b/rust/hw/timer/hpet/src/devi= ce.rs index 79d818b43da..19676af74bc 100644 --- a/rust/hw/timer/hpet/src/device.rs +++ b/rust/hw/timer/hpet/src/device.rs @@ -383,14 +383,15 @@ fn update_irq(&self, regs: &mut HPETRegisters, set: b= ool) { self.set_irq(regs, set); } =20 - fn arm_timer(&self, tn_regs: &mut HPETTimerRegisters, tick: u64) { + fn arm_timer(&self, regs: &mut HPETRegisters, tick: u64) { // &HPETRegisters should be gotten from BqlRefCell, // but there's no lock guard to guarantee this. So we have to chec= k BQL // context explicitly. This check should be removed when we switch= to // Mutex. assert!(bql::is_locked()); =20 - let mut ns =3D self.get_state().get_ns(tick); + let mut ns =3D regs.get_ns(tick); + let tn_regs =3D &mut regs.tn_regs[self.index as usize]; =20 // Clamp period to reasonable min value (1 us) if tn_regs.is_periodic() && ns - tn_regs.last < 1000 { @@ -408,21 +409,22 @@ fn set_timer(&self, regs: &mut HPETRegisters) { // Mutex. assert!(bql::is_locked()); =20 + let cur_tick: u64 =3D regs.get_ticks(); let tn_regs =3D &mut regs.tn_regs[self.index as usize]; - let cur_tick: u64 =3D self.get_state().get_ticks(); =20 tn_regs.wrap_flag =3D 0; tn_regs.update_cmp64(cur_tick); + + let mut next_tick: u64 =3D tn_regs.cmp64; if tn_regs.is_32bit_mod() { // HPET spec says in one-shot 32-bit mode, generate an interru= pt when // counter wraps in addition to an interrupt with comparator m= atch. if !tn_regs.is_periodic() && tn_regs.cmp64 > hpet_next_wrap(cu= r_tick) { tn_regs.wrap_flag =3D 1; - self.arm_timer(tn_regs, hpet_next_wrap(cur_tick)); - return; + next_tick =3D hpet_next_wrap(cur_tick); } } - self.arm_timer(tn_regs, tn_regs.cmp64); + self.arm_timer(regs, next_tick); } =20 fn del_timer(&self, regs: &mut HPETRegisters) { @@ -584,8 +586,8 @@ fn callback(&self, regs: &mut HPETRegisters) { // Mutex. assert!(bql::is_locked()); =20 + let cur_tick: u64 =3D regs.get_ticks(); let tn_regs =3D &mut regs.tn_regs[self.index as usize]; - let cur_tick: u64 =3D self.get_state().get_ticks(); =20 if tn_regs.is_periodic() && tn_regs.period !=3D 0 { while hpet_time_after(cur_tick, tn_regs.cmp64) { @@ -596,11 +598,11 @@ fn callback(&self, regs: &mut HPETRegisters) { } else { tn_regs.cmp =3D tn_regs.cmp64; } - self.arm_timer(tn_regs, tn_regs.cmp64); } else if tn_regs.wrap_flag !=3D 0 { tn_regs.wrap_flag =3D 0; - self.arm_timer(tn_regs, tn_regs.cmp64); } + let next_tick =3D tn_regs.cmp64; + self.arm_timer(regs, next_tick); self.update_irq(regs, true); } =20 @@ -663,9 +665,22 @@ pub struct HPETRegisters { =20 /// HPET Timer N Registers tn_regs: [HPETTimerRegisters; HPET_MAX_TIMERS], + + /// Offset of main counter relative to qemu clock. + pub hpet_offset: u64, } =20 impl HPETRegisters { + fn get_ticks(&self) -> u64 { + // Protect hpet_offset in lockless IO case which would not lock BQ= L. + ns_to_ticks(CLOCK_VIRTUAL.get_ns() + self.hpet_offset) + } + + fn get_ns(&self, tick: u64) -> u64 { + // Protect hpet_offset in lockless IO case which would not lock BQ= L. + ticks_to_ns(tick) - self.hpet_offset + } + fn is_legacy_mode(&self) -> bool { self.config & (1 << HPET_CFG_LEG_RT_SHIFT) !=3D 0 } @@ -693,8 +708,7 @@ pub struct HPETState { #[property(rename =3D "msi", bit =3D HPET_FLAG_MSI_SUPPORT_SHIFT, defa= ult =3D false)] flags: u32, =20 - /// Offset of main counter relative to qemu clock. - hpet_offset: BqlCell, + hpet_offset_migration: BqlCell, #[property(rename =3D "hpet-offset-saved", default =3D true)] hpet_offset_saved: bool, =20 @@ -726,14 +740,6 @@ const fn has_msi_flag(&self) -> bool { self.flags & (1 << HPET_FLAG_MSI_SUPPORT_SHIFT) !=3D 0 } =20 - fn get_ticks(&self) -> u64 { - ns_to_ticks(CLOCK_VIRTUAL.get_ns() + self.hpet_offset.get()) - } - - fn get_ns(&self, tick: u64) -> u64 { - ticks_to_ns(tick) - self.hpet_offset.get() - } - fn handle_legacy_irq(&self, irq: u32, level: u32) { let regs =3D self.regs.borrow(); if irq =3D=3D HPET_LEGACY_PIT_INT { @@ -779,8 +785,7 @@ fn set_cfg_reg(&self, regs: &mut HPETRegisters, shift: = u32, len: u32, val: u64) =20 if activating_bit(old_val, new_val, HPET_CFG_ENABLE_SHIFT) { // Enable main counter and interrupt generation. - self.hpet_offset - .set(ticks_to_ns(regs.counter) - CLOCK_VIRTUAL.get_ns()); + regs.hpet_offset =3D ticks_to_ns(regs.counter) - CLOCK_VIRTUAL= .get_ns(); =20 for timer in self.timers.iter().take(self.num_timers) { let t =3D timer.borrow(); @@ -794,7 +799,7 @@ fn set_cfg_reg(&self, regs: &mut HPETRegisters, shift: = u32, len: u32, val: u64) } } else if deactivating_bit(old_val, new_val, HPET_CFG_ENABLE_SHIFT= ) { // Halt main counter and disable interrupt generation. - regs.counter =3D self.get_ticks(); + regs.counter =3D regs.get_ticks(); =20 for timer in self.timers.iter().take(self.num_timers) { timer.borrow().del_timer(regs); @@ -873,7 +878,7 @@ unsafe fn init(mut this: ParentInit) { // initialized memory to all zeros - simple types (bool/u32/usize)= can // rely on this without explicit initialization. uninit_field_mut!(*this, regs).write(Default::default()); - uninit_field_mut!(*this, hpet_offset).write(Default::default()); + uninit_field_mut!(*this, hpet_offset_migration).write(Default::def= ault()); // Set null_mut for now and post_init() will fill it. uninit_field_mut!(*this, irqs).write(Default::default()); uninit_field_mut!(*this, rtc_irq_level).write(Default::default()); @@ -929,6 +934,7 @@ fn reset_hold(&self, _type: ResetType) { =20 regs.counter =3D 0; regs.config =3D 0; + regs.hpet_offset =3D 0; HPETFwConfig::update_hpet_cfg( self.hpet_id.get(), regs.capability as u32, @@ -937,7 +943,6 @@ fn reset_hold(&self, _type: ResetType) { } =20 self.pit_enabled.set(true); - self.hpet_offset.set(0); =20 // to document that the RTC lowers its output on reset as well self.rtc_irq_level.set(0); @@ -982,7 +987,7 @@ fn read(&self, addr: hwaddr, size: u32) -> u64 { Global(INT_STATUS) =3D> regs.int_status, Global(COUNTER) =3D> { let cur_tick =3D if regs.is_hpet_enabled() { - self.get_ticks() + regs.get_ticks() } else { regs.counter }; @@ -1018,8 +1023,9 @@ fn write(&self, addr: hwaddr, value: u64, size: u32) { =20 fn pre_save(&self) -> Result<(), migration::Infallible> { let mut regs =3D self.regs.borrow_mut(); + self.hpet_offset_migration.set(regs.hpet_offset); if regs.is_hpet_enabled() { - regs.counter =3D self.get_ticks(); + regs.counter =3D regs.get_ticks(); } =20 /* @@ -1044,9 +1050,10 @@ fn post_load(&self, _version_id: u8) -> Result<(), m= igration::Infallible> { =20 // Recalculate the offset between the main counter and guest time if !self.hpet_offset_saved { - self.hpet_offset + self.hpet_offset_migration .set(ticks_to_ns(regs.counter) - CLOCK_VIRTUAL.get_ns()); } + regs.hpet_offset =3D self.hpet_offset_migration.get(); =20 Ok(()) } @@ -1098,7 +1105,7 @@ impl ObjectImpl for HPETState { .minimum_version_id(1) .needed(&HPETState::is_offset_needed) .fields(vmstate_fields! { - vmstate_of!(HPETState, hpet_offset), + vmstate_of!(HPETState, hpet_offset_migration), }) .build(); =20 --=20 2.51.1 From nobody Sun Dec 14 06:42:49 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1763369335; cv=none; d=zohomail.com; s=zohoarc; b=BPgTKNQlORfq2jOuBovoJJ/6nli7xq4zWdQg3ttTfrB9YxtVX6EjXVWL0OW8nWkhSicJI2QYSLkryh0ajTyr33MBFjb67YmtjzO+eqovkgV5ouJUxF5DKoR4lUtellfpTew+XLusG7DVvAhcFdy6ZWg9rlK3Pz5/wXMHJtm8M6s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1763369335; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=bXWL09IpvxzHJJZXvTmfbHjqEOYFpT3gc+RY/7fbQEk=; b=b99mWD1ZCy0/uvH/gicftKJ1XE/PECp7QpuLMwxBVKcfAnGpsqTqORO9orTCyB1sSAB8vSrrNQ1FPHOzFa8NBj7zyzDJjqN4SvhecTtAZzzZMaHtMSKQMaqzTxIs9jnipbR7fjZ50B14w57fC70FI0s6q2WgUr92VWk0i6L3PfQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 17633693356911021.5185696149222; Mon, 17 Nov 2025 00:48:55 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vKuuD-00048s-C8; Mon, 17 Nov 2025 03:48:13 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vKuuB-00044X-1R for qemu-devel@nongnu.org; Mon, 17 Nov 2025 03:48:11 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vKuu8-00071a-FN for qemu-devel@nongnu.org; Mon, 17 Nov 2025 03:48:10 -0500 Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-661--024tjmnMNOLOttaDIoKlw-1; Mon, 17 Nov 2025 03:48:05 -0500 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-4775f51ce36so33810725e9.1 for ; Mon, 17 Nov 2025 00:48:05 -0800 (PST) Received: from [192.168.10.48] ([176.206.119.13]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4778bae1122sm113161345e9.0.2025.11.17.00.48.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Nov 2025 00:48:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1763369287; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bXWL09IpvxzHJJZXvTmfbHjqEOYFpT3gc+RY/7fbQEk=; b=KSQzXqZTYpOQPq2eT2XYYivNe85e2YB+VbRViED/6WavEwWfPrLJjlb4ALsm1gZaKuSL5V PS0P1R6JPFYsk3mT6QUMapjDrRTXjZrnkHdVWM66un/41cZzmD/DRCyifm3HBkQGs1qN9l 5IOEaqlXBkWc9m1BzfVk3wp9MEuQGfc= X-MC-Unique: -024tjmnMNOLOttaDIoKlw-1 X-Mimecast-MFC-AGG-ID: -024tjmnMNOLOttaDIoKlw_1763369285 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1763369284; x=1763974084; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=bXWL09IpvxzHJJZXvTmfbHjqEOYFpT3gc+RY/7fbQEk=; b=OmNQZz0+Gt5s+lM52ryRGtypza14py5YyXV3uTGn4XfBpOaBDry4rMpZj1XQqsgDr0 FSX8s/sRbCaE8zqPzPZstlam5lrxuItJughzw6k9T3/yYzKSA+Isevx1bhdYI7mQhvBQ 6+8cfcX/pP8pZHgVx57tqgdixNFIN8anR2DTLh9i4Z0Mte31aqqHq8Sz2Howx2ELnesR jSVvbtuL5E8j/9bS2CFgl5L2+CUFM7ntEFbiP1PifHuRhdYsIcXIkrVhRDCPDl3vJ1Ru lRYO+NcTX8i3CvPUhnmKpnHO1ul4w88tdrUPbBL1pZnUe+iBMfp4SFhpQcBNvzKjFzgx czAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763369284; x=1763974084; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=bXWL09IpvxzHJJZXvTmfbHjqEOYFpT3gc+RY/7fbQEk=; b=iYDyaohyp5DrxX8GZP07Vt1jllElvY2G0bW26vf6RsnjxUIe05xIBIrnyNG2EhWsHB 0kisVg8+/sL2MouVCPdon3ThqKRkCjmQsw1RmdL6730SCpxHMuUFOuqMahIZhOf9JXss /9C+HlXsuZ86zsuEZazlUOpuiaGrSzmD0dPA8+U1jOOiLWXr4bD5xCyulhsuMDyV+lRn T1gqwnN4X71rADFRz56hTRsVbLPA7/uMINkMjhqdLka+PZ4oaGfJAUxhyRxpDra6STVY 8FqbHC/3QRyiKQ7TQnF2XGSdwnXsjL9TvFeUjhrq8/x/N013KMURjRObqYdsceu9Q2Yk nWkg== X-Gm-Message-State: AOJu0YxYogUDTHjfAD3X6GUcLJ+skSwCgw9nT0IEAxbfijM4Xb1hGh1/ orbdismYT0N77z9fNCBZHq/KrjxvYg0OMNxQgNMpxtPVnjE0nUQCPqIvsN5zxI9yqoOr32ZOb+b jtQf+vB6dOogi2wOVYkW8sNC8yfnNsIukKvBqSQlegYhSYUMft2U1IO/x2qphF8yvSG+UTpG1rt VgZ9zkGg6CurWRgDDLs4hLkqiLhauOax9A55DzVIlm X-Gm-Gg: ASbGncu89jfOhLP+4fiILaqyxzz3HesrejG/49vRYeE2Baxst5zRvWzMYC5q/hywSQV yXW5/d8i18SKzZpvs8zscz5cjLkUA/JhalKjS1C3lJCsZrAK9DBw5p3AbRAJnHn0vAqO2bzHkkB nU0gMfo4gX5Qm8IPW5eNuGW1pfXvvrCOeTM4xH8B/rYbguk78RnKsWLyNufEJd5EXqp3zCxyKUn IcctWnV5rTksmKCSRVoaKvtCEjpac/3BQYeHLUrz/kJ1Ry0h8cmdmr0aHWAmwfc1xxWPGSoi4sV arAoyzGHfhMki9QNLadB92Y6P1foEeo13tVD/ygOecFMon/adh4MAOQO5Ns1No2X/7kncEhk2iX FA6t903vwsfjG+qR5CmQmVuCRXeJ02uEYZCezFJ+5v/K4n3U+fo5ORt3wOmyxbUAtQOlEhvo9RN nrzh/k X-Received: by 2002:a05:600c:4fcf:b0:477:63b5:6f39 with SMTP id 5b1f17b1804b1-4778fe9ab26mr96050965e9.19.1763369283889; Mon, 17 Nov 2025 00:48:03 -0800 (PST) X-Google-Smtp-Source: AGHT+IF0ztVFNwTbxHTpp0X4RABgpbGcZmzYcWa+a09nVBRT8CMcaQAFP3/azAIRVghZvEQIoH3Fag== X-Received: by 2002:a05:600c:4fcf:b0:477:63b5:6f39 with SMTP id 5b1f17b1804b1-4778fe9ab26mr96050615e9.19.1763369283275; Mon, 17 Nov 2025 00:48:03 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, zhao1.liu@intel.com Subject: [PATCH 3/5] rust/hpet: remove BqlRefCell around HPETTimer Date: Mon, 17 Nov 2025 09:47:50 +0100 Message-ID: <20251117084752.203219-4-pbonzini@redhat.com> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251117084752.203219-1-pbonzini@redhat.com> References: <20251117084752.203219-1-pbonzini@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1763369337384153000 Content-Type: text/plain; charset="utf-8" HPETTimer now has all of its state stored in HPETRegisters, so it does not need its own BqlRefCell anymore. Signed-off-by: Paolo Bonzini Reviewed-by: Zhao Liu --- rust/hw/timer/hpet/src/device.rs | 53 ++++++++++++++++---------------- rust/util/src/timer.rs | 12 +++++--- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/rust/hw/timer/hpet/src/device.rs b/rust/hw/timer/hpet/src/devi= ce.rs index 19676af74bc..5bcf151a680 100644 --- a/rust/hw/timer/hpet/src/device.rs +++ b/rust/hw/timer/hpet/src/device.rs @@ -126,7 +126,7 @@ enum DecodedRegister<'a> { Global(GlobalRegister), =20 /// Register in the timer block `0x100`...`0x3ff` - Timer(&'a BqlRefCell, TimerRegister), + Timer(&'a HPETTimer, TimerRegister), =20 /// Invalid address #[allow(dead_code)] @@ -170,8 +170,7 @@ const fn deactivating_bit(old: u64, new: u64, shift: us= ize) -> bool { (old & mask !=3D 0) && (new & mask =3D=3D 0) } =20 -fn timer_handler(timer_cell: &BqlRefCell) { - let t =3D timer_cell.borrow(); +fn timer_handler(t: &HPETTimer) { // SFAETY: state field is valid after timer initialization. let regs =3D &mut unsafe { t.state.as_ref() }.regs.borrow_mut(); t.callback(regs) @@ -277,12 +276,16 @@ fn new(index: u8, state: *const HPETState) -> HPETTim= er { } } =20 - fn init_timer_with_cell(cell: &BqlRefCell) { - let mut timer =3D cell.borrow_mut(); - // SAFETY: HPETTimer is only used as part of HPETState, which is - // always pinned. - let qemu_timer =3D unsafe { Pin::new_unchecked(&mut timer.qemu_tim= er) }; - qemu_timer.init_full(None, CLOCK_VIRTUAL, Timer::NS, 0, timer_hand= ler, cell); + fn init_timer(timer: Pin<&mut Self>) { + Timer::init_full( + timer, + None, + CLOCK_VIRTUAL, + Timer::NS, + 0, + timer_handler, + |t| &mut t.qemu_timer, + ); } =20 fn get_state(&self) -> &HPETState { @@ -726,7 +729,7 @@ pub struct HPETState { =20 /// HPET timer array managed by this timer block. #[doc(alias =3D "timer")] - timers: [BqlRefCell; HPET_MAX_TIMERS], + timers: [HPETTimer; HPET_MAX_TIMERS], #[property(rename =3D "timers", default =3D HPET_MIN_TIMERS)] num_timers: usize, num_timers_save: BqlCell, @@ -761,11 +764,10 @@ fn init_timers(this: &mut MaybeUninit) { =20 // Initialize in two steps, to avoid calling Timer::init_full = on a // temporary that can be moved. - let timer =3D timer.write(BqlRefCell::new(HPETTimer::new( - index.try_into().unwrap(), - state, - ))); - HPETTimer::init_timer_with_cell(timer); + let timer =3D timer.write(HPETTimer::new(index.try_into().unwr= ap(), state)); + // SAFETY: HPETState is pinned + let timer =3D unsafe { Pin::new_unchecked(timer) }; + HPETTimer::init_timer(timer); } } =20 @@ -787,8 +789,7 @@ fn set_cfg_reg(&self, regs: &mut HPETRegisters, shift: = u32, len: u32, val: u64) // Enable main counter and interrupt generation. regs.hpet_offset =3D ticks_to_ns(regs.counter) - CLOCK_VIRTUAL= .get_ns(); =20 - for timer in self.timers.iter().take(self.num_timers) { - let t =3D timer.borrow(); + for t in self.timers.iter().take(self.num_timers) { let id =3D t.index as usize; let tn_regs =3D ®s.tn_regs[id]; =20 @@ -801,8 +802,8 @@ fn set_cfg_reg(&self, regs: &mut HPETRegisters, shift: = u32, len: u32, val: u64) // Halt main counter and disable interrupt generation. regs.counter =3D regs.get_ticks(); =20 - for timer in self.timers.iter().take(self.num_timers) { - timer.borrow().del_timer(regs); + for t in self.timers.iter().take(self.num_timers) { + t.del_timer(regs); } } =20 @@ -830,9 +831,9 @@ fn set_int_status_reg(&self, regs: &mut HPETRegisters, = shift: u32, _len: u32, va let new_val =3D val << shift; let cleared =3D new_val & regs.int_status; =20 - for (index, timer) in self.timers.iter().take(self.num_timers).enu= merate() { - if cleared & (1 << index) !=3D 0 { - timer.borrow().update_irq(regs, false); + for t in self.timers.iter().take(self.num_timers) { + if cleared & (1 << t.index) !=3D 0 { + t.update_irq(regs, false); } } } @@ -928,8 +929,8 @@ fn reset_hold(&self, _type: ResetType) { { let mut regs =3D self.regs.borrow_mut(); =20 - for timer in self.timers.iter().take(self.num_timers) { - timer.borrow().reset(&mut regs); + for t in self.timers.iter().take(self.num_timers) { + t.reset(&mut regs); } =20 regs.counter =3D 0; @@ -981,7 +982,7 @@ fn read(&self, addr: hwaddr, size: u32) -> u64 { use DecodedRegister::*; use GlobalRegister::*; (match target { - Timer(timer, tn_target) =3D> timer.borrow().read(tn_target, re= gs), + Timer(t, tn_target) =3D> t.read(tn_target, regs), Global(CAP) =3D> regs.capability, /* including HPET_PERIOD 0x0= 04 */ Global(CFG) =3D> regs.config, Global(INT_STATUS) =3D> regs.int_status, @@ -1012,7 +1013,7 @@ fn write(&self, addr: hwaddr, value: u64, size: u32) { use DecodedRegister::*; use GlobalRegister::*; match target { - Timer(timer, tn_target) =3D> timer.borrow().write(tn_target, r= egs, value, shift, len), + Timer(t, tn_target) =3D> t.write(tn_target, regs, value, shift= , len), Global(CAP) =3D> {} // General Capabilities and ID Register: R= ead Only Global(CFG) =3D> self.set_cfg_reg(regs, shift, len, value), Global(INT_STATUS) =3D> self.set_int_status_reg(regs, shift, l= en, value), diff --git a/rust/util/src/timer.rs b/rust/util/src/timer.rs index c6b3e4088ec..829f52d111e 100644 --- a/rust/util/src/timer.rs +++ b/rust/util/src/timer.rs @@ -45,14 +45,14 @@ impl Timer { } =20 /// Create a new timer with the given attributes. - pub fn init_full<'timer, 'opaque: 'timer, T, F>( - self: Pin<&'timer mut Self>, + pub fn init_full( + opaque: Pin<&mut T>, timer_list_group: Option<&TimerListGroup>, clk_type: ClockType, scale: u32, attributes: u32, _cb: F, - opaque: &'opaque T, + field: impl FnOnce(&mut T) -> &mut Self, ) where F: for<'a> FnCall<(&'a T,)>, { @@ -70,8 +70,10 @@ pub fn init_full<'timer, 'opaque: 'timer, T, F>( =20 // SAFETY: the opaque outlives the timer unsafe { + let opaque =3D Pin::into_inner_unchecked(opaque); + let timer =3D field(opaque).as_mut_ptr(); timer_init_full( - self.as_mut_ptr(), + timer, if let Some(g) =3D timer_list_group { g as *const TimerListGroup as *mut _ } else { @@ -81,7 +83,7 @@ pub fn init_full<'timer, 'opaque: 'timer, T, F>( scale as c_int, attributes as c_int, Some(timer_cb), - (opaque as *const T).cast::().cast_mut(), + (opaque as *mut T).cast::(), ) } } --=20 2.51.1 From nobody Sun Dec 14 06:42:49 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1763369369; cv=none; d=zohomail.com; s=zohoarc; b=j/v8MmnnyvixCbh3Lc/rqzHJ/UP3bCqNyvCMqgkJ80lpxOjhGiTWndsjdGeHIl3usR/2AYAnT7UADotkernUwtl67LCx7mcMa5gushClL5KVdGDLG1OvT8isnTlGZi6uRYmf3WdPUT9Ku9VMsglxQVijYCmdrrE5cLCI8Ckfhe8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1763369369; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=13wjDJAbYFD10gI6Zr7kk4dq3n61G4FXpl1Z3qYzA6A=; b=YiwoU9VCWP116YtHUvK/wU5cTKNrLnVbgwZ9QeVIVfqGsDOonpX1oIUIEGUCfn58UzfawTIWMRKA3W8G5v/P4Eo4YZe374GQBELz51AEsCr61iwiMeVGyhMIHLh0yiLR1iac2q2lhqpt0Y5g/9L7zU7V28k37SOCFaqTUFTk038= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1763369369163156.15888064316857; Mon, 17 Nov 2025 00:49:29 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vKuuE-0004Aq-Sd; Mon, 17 Nov 2025 03:48:14 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vKuuC-000471-CC for qemu-devel@nongnu.org; Mon, 17 Nov 2025 03:48:12 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vKuuA-00071v-CM for qemu-devel@nongnu.org; Mon, 17 Nov 2025 03:48:12 -0500 Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-91-9sHBLJIXNMGUTRDVMYbZBg-1; Mon, 17 Nov 2025 03:48:07 -0500 Received: by mail-wm1-f72.google.com with SMTP id 5b1f17b1804b1-47496b3c1dcso56033555e9.3 for ; Mon, 17 Nov 2025 00:48:07 -0800 (PST) Received: from [192.168.10.48] ([176.206.119.13]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4779920f2cdsm135766415e9.10.2025.11.17.00.48.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Nov 2025 00:48:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1763369289; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=13wjDJAbYFD10gI6Zr7kk4dq3n61G4FXpl1Z3qYzA6A=; b=Awaf1xNnb7mCXJLjHsJ0H6NjXrk06oZwul3h7FsSZ104FjjJqQ9+Quf0DPJHqzUcE5ZQK+ 041+oO4i4rMQ4iRktgi0tSqhRgnmXYWWjd1E6Lx1+oFtoR1jsYY+4V9rfQt8CDWnH9kL1B MhxP5TUiTEEM10AQIvIJheRjGhyKny0= X-MC-Unique: 9sHBLJIXNMGUTRDVMYbZBg-1 X-Mimecast-MFC-AGG-ID: 9sHBLJIXNMGUTRDVMYbZBg_1763369287 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1763369286; x=1763974086; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=13wjDJAbYFD10gI6Zr7kk4dq3n61G4FXpl1Z3qYzA6A=; b=oXFL5bxMCw1U6QyfF8NSve5jsM5d0teFaCCe3yumih5u8lTBrVEseGtsGVljWEOZnb ZPxQufaPNQNV8ixwiPOfZt8zCytOTMoPElhdX+t1hGduc5xdx1O8Cswsg2Xnhyej/21B chLIe2pmTQV5AEXiDeWRG8em/mfSCba01rji1MrYzzjEw5qtkEgredKQOAGWQfnRVz83 HGycXldGOQIu766bbBjMT+XQ+/BdYzXLFpQwQdvp4UxfWlRy2pPqgkSOygpsdO7iXy1u GL6VGnS/zsii6yrqWic3Sx/dRgkA3jRA5FqTEf+VQkPnu8Z7WussRW4pJcY6PQ63XGh1 u40w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763369286; x=1763974086; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=13wjDJAbYFD10gI6Zr7kk4dq3n61G4FXpl1Z3qYzA6A=; b=l8WDT4WL2NDyCoAPQYrGT7mxI3d2GlHgHT9bCoNMaD+fehK5r9emJ6Nm8R+Qm9YpKk Hh3reyNithQSuJzguSmvzq6ORj2KSbqY6Of9X1vKPQWxqudr9JYnJEvZnj3DsoCgomo6 TybIAwSsSgAWhtKgm0T4PQI0BRDoSbNFbR+fK6Q86DNIeif9Eam3/l1hHd8+ogX+/a/X Pc+bqNv7y5FogdAko/ufWs9K+3pAUJE647i2OuvtR5KDNuhEYu86YvZdaX8xcjzComW0 ySAcG5TbitDfH1OlI4r5tterLiGmN05P+NpbGwcfbt5i4pY5kBTQTVWQHjwzcMMpx7gX Qltw== X-Gm-Message-State: AOJu0Yw2S/wa9mB9u1IWBbMXhOzH0J60hfC/FcbITH/nv5anV6FnFX+X DgclvuuO++U0ofF6TnKwV5mBmLztv2cRkPNvtTqJvRuVwIT2bgYkOFYRXpCF1VS3sVPv6GSBCt+ THEEC1mtn+MzxNfio1GnowV+MeJP29nNln298bWMyBAqt0NKLCzGF93CqdKUSn0K+Ns4BIsPMFe ghmopwH2vtx6BFjKnNSJCdbMGMHU0xwkRj6hv6vIoB X-Gm-Gg: ASbGnct0aoe2AJvoijIVwbmEVDQfHds96zEptSM5QkCdh3pA8N5bze1GSxoCqjSRwAK Odc7vPoLHZdqGRwwty27qYosDA14LbQht8DameXsw7IxXHUxj++Q3BaqSRiMnBoBshq9lXa9N4D qGh1WU4iIcu0dHh02JsoStIFDNbZoA2dFncazQkQApxJDM4eFsUPsIFolxk3oIKss2NCIpkObW4 0dev0N6/04iORGe5UI4JLZ2enwOAbOcY2W32VaB56JePLgy/se+1DXnyvYU3JrqIdmaNIiv3Enf SjGuuOziyJkRsrxkRAwcvsLJS3ctxJh8sFHq7H3L0N+7x3CiGuk5IXsDkhszHuUHy4lfimgzwIh SKZTk26tt988lF1CyJfIa1A/y/V3FQ4hdYeDiouJsMnDnb/LcFKqo291h4VD5akxxxlbQ9ZFCfY LiJMOw X-Received: by 2002:a05:600c:8b4b:b0:477:755b:5587 with SMTP id 5b1f17b1804b1-4778fe55405mr120246565e9.8.1763369286151; Mon, 17 Nov 2025 00:48:06 -0800 (PST) X-Google-Smtp-Source: AGHT+IHO3LBJn+YbU5X+iaa8JqvmzPeaJKA7gO3VOUKYsFmhe8jI/H7VeCvb+7GHo+9dafbY/erqlQ== X-Received: by 2002:a05:600c:8b4b:b0:477:755b:5587 with SMTP id 5b1f17b1804b1-4778fe55405mr120246225e9.8.1763369285641; Mon, 17 Nov 2025 00:48:05 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, zhao1.liu@intel.com Subject: [PATCH 4/5] rust: migration: implement ToMigrationState for Timer Date: Mon, 17 Nov 2025 09:47:51 +0100 Message-ID: <20251117084752.203219-5-pbonzini@redhat.com> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251117084752.203219-1-pbonzini@redhat.com> References: <20251117084752.203219-1-pbonzini@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1763369371711153000 Content-Type: text/plain; charset="utf-8" Timer is a complex struct, allow adding it to a struct that uses #[derive(ToMigrationState)]; similar to vmstate_timer, only the expiration time has to be preserved. In fact, because it is thread-safe, ToMigrationStateShared can also be implemented without needing a cell or mutex that wraps the timer. Signed-off-by: Paolo Bonzini --- rust/hw/timer/hpet/src/device.rs | 1 - rust/migration/src/migratable.rs | 31 +++++++++++++++++++++++++++++++ rust/util/src/timer.rs | 10 +++++++++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/rust/hw/timer/hpet/src/device.rs b/rust/hw/timer/hpet/src/devi= ce.rs index 5bcf151a680..373ec37bbd3 100644 --- a/rust/hw/timer/hpet/src/device.rs +++ b/rust/hw/timer/hpet/src/device.rs @@ -250,7 +250,6 @@ const fn get_individual_route(&self) -> usize { } =20 /// HPET Timer Abstraction -#[repr(C)] #[derive(Debug)] pub struct HPETTimer { /// timer N index within the timer block (`HPETState`) diff --git a/rust/migration/src/migratable.rs b/rust/migration/src/migratab= le.rs index 02efe31d72c..c82a6b9a7cf 100644 --- a/rust/migration/src/migratable.rs +++ b/rust/migration/src/migratable.rs @@ -140,6 +140,26 @@ fn restore_migrated_state_mut( =20 impl_for_primitive!(u8, u16, u32, u64, i8, i16, i32, i64, bool); =20 +impl ToMigrationState for util::timer::Timer { + type Migrated =3D i64; + + fn snapshot_migration_state(&self, target: &mut i64) -> Result<(), Inv= alidError> { + // SAFETY: as_ptr() is unsafe to ensure that the caller reasons ab= out + // the pinning of the data inside the Opaque<>. Here all we do is + // access a field. + *target =3D self.expire_time_ns().unwrap_or(-1); + Ok(()) + } + + fn restore_migrated_state_mut( + &mut self, + source: Self::Migrated, + version_id: u8, + ) -> Result<(), InvalidError> { + self.restore_migrated_state(source, version_id) + } +} + impl ToMigrationState for [T; N] where [T::Migrated; N]: Default, @@ -237,6 +257,17 @@ fn restore_migrated_state( ) -> Result<(), InvalidError>; } =20 +impl ToMigrationStateShared for util::timer::Timer { + fn restore_migrated_state(&self, source: i64, _version_id: u8) -> Resu= lt<(), InvalidError> { + if source >=3D 0 { + self.modify(source as u64); + } else { + self.delete(); + } + Ok(()) + } +} + impl ToMigrationStateShared for= [T; N] where [T::Migrated; N]: Default, diff --git a/rust/util/src/timer.rs b/rust/util/src/timer.rs index 829f52d111e..4109d84c398 100644 --- a/rust/util/src/timer.rs +++ b/rust/util/src/timer.rs @@ -10,7 +10,8 @@ use common::{callbacks::FnCall, Opaque}; =20 use crate::bindings::{ - self, qemu_clock_get_ns, timer_del, timer_init_full, timer_mod, QEMUCl= ockType, + self, qemu_clock_get_ns, timer_del, timer_expire_time_ns, timer_init_f= ull, timer_mod, + QEMUClockType, }; =20 /// A safe wrapper around [`bindings::QEMUTimer`]. @@ -88,6 +89,13 @@ pub fn init_full( } } =20 + pub fn expire_time_ns(&self) -> Option { + // SAFETY: the only way to obtain a Timer safely is via methods th= at + // take a Pin<&mut Self>, therefore the timer is pinned + let ret =3D unsafe { timer_expire_time_ns(self.as_ptr()) }; + i64::try_from(ret).ok() + } + pub fn modify(&self, expire_time: u64) { // SAFETY: the only way to obtain a Timer safely is via methods th= at // take a Pin<&mut Self>, therefore the timer is pinned --=20 2.51.1 From nobody Sun Dec 14 06:42:49 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1763369369; cv=none; d=zohomail.com; s=zohoarc; b=ioh3BZhLrUmW9wi7wOq50VLf8U3nPiaqq0/IC9Je1LEeltXYrOJY5+BUpm0RMyYD3vcma9QQLp668qLW71DvyUPt2IdwBehg3SO+S5OoDxxBbIwrg0zITEh1WO7tpKXw2M+2ipnGIRkeG1OYP391B3h8GHte/9STm7JM/81E9WQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1763369369; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=XAhaWrOrXw2Sb3mRyhoDdnRIUBL1rpuESpFW8PbKSLU=; b=YpSJYxplX9vNZhD9AWxYplxBLbfCgaZBu1Jz8c/EyzBY6ZVeYbkiIvZUK7ne1dyU9Z6FTuT16aGhQa9jbMBqp8W4Z7Ns4xktyvUWkKTJVcctGsJ5YOUqzOLBMS5nu3x4EbXjoj3/sJR+4eREXx/bJFsigVqJFqwaSlQ3dc0bhYM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1763369369010656.3871122832818; Mon, 17 Nov 2025 00:49:29 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vKuuI-0004IC-Lm; Mon, 17 Nov 2025 03:48:18 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vKuuE-0004B8-NM for qemu-devel@nongnu.org; Mon, 17 Nov 2025 03:48:14 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vKuuC-00072R-Nm for qemu-devel@nongnu.org; Mon, 17 Nov 2025 03:48:14 -0500 Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-684-jgJTKaPsOSanJ_EOGPXa0w-1; Mon, 17 Nov 2025 03:48:10 -0500 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-477964c22e0so14123345e9.0 for ; Mon, 17 Nov 2025 00:48:10 -0800 (PST) Received: from [192.168.10.48] ([176.206.119.13]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-47787e8e6a1sm287075055e9.11.2025.11.17.00.48.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Nov 2025 00:48:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1763369292; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XAhaWrOrXw2Sb3mRyhoDdnRIUBL1rpuESpFW8PbKSLU=; b=d+FJNgPeUIdWeWY2LyWbxZAiI9RLvY/v+p8HNCDMR7QyDan6gVVPH3vW2rTuqT30NQSos1 3UZejNm2vc/kaKtpyPJW7bF/jww+Z9qeSwPku5ZA23Ck+VT1xrfwQANBr5ucppSP+WU3AU Xm9p4qikuQa/b2Z0Rf/VwjR37p+I78Q= X-MC-Unique: jgJTKaPsOSanJ_EOGPXa0w-1 X-Mimecast-MFC-AGG-ID: jgJTKaPsOSanJ_EOGPXa0w_1763369289 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1763369288; x=1763974088; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=XAhaWrOrXw2Sb3mRyhoDdnRIUBL1rpuESpFW8PbKSLU=; b=ee+eTHKrZAl46zZ7ORjo+N5ujM6zdYWJ9cPsIZmq9+xlgDmxG0Uk4PPL2VMRqnI4OW SNKfEfO03LAkjTbFc4DFNHEwPPO/ece26x6A1b2xfIj7bJ5mgkeNsdOGyVUTgWvZnqSI y7cnl662KB2V1ENW4tgoN43UP3AQSvhqXyYShLJSdGRPjFXdGv+Tqq7humRDD3XdvQ7X WgaCOvDK3F0XnmmHYPB70xUlKw8mDMwT95cuBD1OSBQSvOzt/qIZQT79k1J/tKLO0H8c /fQudoYXRZkW12S1N6fRRv1GKJEF3oM+Txwqj5BvsQhrEtT+7l1dpAuuDvKPwamebk4V bQVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763369288; x=1763974088; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=XAhaWrOrXw2Sb3mRyhoDdnRIUBL1rpuESpFW8PbKSLU=; b=lnOFP7o2bgbapFOn4koJG/M+jinJGcOHbkf9ufLXgsW90riNkTLX2JsHS0rNXlNYKk ot6RFjBA1l5jfIvSridkUh3Yn6KHmGQflb9Cb3/vPIuRc6LKSbA4N9uqwDvDy3nXECgY z1Ve3IP7lMhTwIXfjg5juUzlzu7iEzGbiwTwhHfia/QWpmKd8d7MLsPuJ9aA9R+m/vQc XjOKlnhMidVfB+yIHh/4mUM8mhGogSoE48r+mXY7aMFYqees9B6rSE0ML95WMaGWofjA /dUo6TZyA1DZ74A0BgI/yss3M422GDK0gfnWvBSjP7zNgsKvqQ7VRSI82HGqDm19mLoH KfkQ== X-Gm-Message-State: AOJu0YydrWCcY/6iWBfgP61WldTC9F0t7UAFhaJ7g6M9p2wywna1FOn1 Vb6tIe2q20p2hGM0pbhF/Oh9obuCjLlyjpLYaMPABEm/QZj9n/ALS1hrlqD1e/uWmnr5+r2+vpa KsRyJqRgPxoiNd1ug4DRqnYUEG5oRBPIMz1CUJuGE7gSQjsaHYjGIu/OzXwZUVbh/hlpEPR1MvN YYRuoSE9LwfS5p9Lp3t6sL3yIGg9Q+QIo1josVTYVz X-Gm-Gg: ASbGncufuVm3v3KWSOFMR9cOHS/cdtguXswAdtSKRR5kZKCzFJSE0qxjJo6dBQRjzhM Eh6zz1V6z9zRPdwaEy169aGgjoM0VKA+GoWzCjn5dpjCnfPWDrrr67nxATqmUM5RR9N2w140KgR OB9Oh8Nl+igAN4YSF0jM1nHPkqC/fypjvRMUhBzQc/BuYdJPJdmNJPAHP4z14k67+2sszf17n7W 28Lt5iMnTUjD3yalBlnZ4DkuiPBw8kVYAd1B0DkwP1xZCBtMdUjAv0jL0kNH3JfM9uoh87+zTV+ bgi6ajgWiibmxw5bauEqNdkFIxFifu0A8R8olebYUzikoEIMY/qRBLRWCcfe6RTsobrq65gnUyT njAay9L58amFIUz2YwEX5DU1QGANwnU6cLKO7pMuoE2+AKvDRMAaSVIYimlqTTr8yCuRcd7fB3z J3qLt9 X-Received: by 2002:a05:600c:4c14:b0:477:9d88:2da6 with SMTP id 5b1f17b1804b1-4779d88318amr34495455e9.0.1763369288386; Mon, 17 Nov 2025 00:48:08 -0800 (PST) X-Google-Smtp-Source: AGHT+IFw0W2ipaq0kWQ1T37VeNBSCQQ8dr59stNSv1yRpErDMjT7NZnpiKOcR/EjdLifFsnEcaCfmw== X-Received: by 2002:a05:600c:4c14:b0:477:9d88:2da6 with SMTP id 5b1f17b1804b1-4779d88318amr34495205e9.0.1763369287812; Mon, 17 Nov 2025 00:48:07 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, zhao1.liu@intel.com Subject: [PATCH 5/5] rust/hpet: Apply Migratable<> wrapper and ToMigrationState Date: Mon, 17 Nov 2025 09:47:52 +0100 Message-ID: <20251117084752.203219-6-pbonzini@redhat.com> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251117084752.203219-1-pbonzini@redhat.com> References: <20251117084752.203219-1-pbonzini@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1763369371791153000 Content-Type: text/plain; charset="utf-8" From: Zhao Liu Before using Mutex<> to protect HPETRegisters, it's necessary to apply Migratable<> wrapper and ToMigrationState first since there's no pre-defined VMState for Mutex<>. In addition, this allows to move data from HPETTimerRegisters to HPETTimer, so as to preserve the original migration format of the C implementation. To do that, HPETTimer is wrapped with Migratable<> as well but the implementation of ToMigrationStateShared is hand-written. Note that even though the HPETRegistersMigration struct is generated by ToMigrationState macro, its VMState still needs to be implemented by hand. Signed-off-by: Zhao Liu Link: https://lore.kernel.org/r/20251113051937.4017675-21-zhao1.liu@intel.c= om [Added HPETTimer implementation and restored compatible migration format. -= Paolo] Signed-off-by: Paolo Bonzini Reviewed-by: Zhao Liu --- rust/hw/timer/hpet/src/device.rs | 139 +++++++++++++++++++++++-------- 1 file changed, 102 insertions(+), 37 deletions(-) diff --git a/rust/hw/timer/hpet/src/device.rs b/rust/hw/timer/hpet/src/devi= ce.rs index 373ec37bbd3..fde4469ec16 100644 --- a/rust/hw/timer/hpet/src/device.rs +++ b/rust/hw/timer/hpet/src/device.rs @@ -13,7 +13,7 @@ use bql::prelude::*; use common::prelude::*; use hwcore::prelude::*; -use migration::{self, prelude::*}; +use migration::{self, prelude::*, ToMigrationStateShared}; use qom::prelude::*; use system::{ bindings::{address_space_memory, address_space_stl_le}, @@ -176,7 +176,6 @@ fn timer_handler(t: &HPETTimer) { t.callback(regs) } =20 -#[repr(C)] #[derive(Debug, Default)] pub struct HPETTimerRegisters { // Memory-mapped, software visible timer registers @@ -650,11 +649,13 @@ fn write( } } =20 -#[repr(C)] -#[derive(Default)] +#[derive(Default, ToMigrationState)] pub struct HPETRegisters { // HPET block Registers: Memory-mapped, software visible registers /// General Capabilities and ID Register + /// + /// Constant and therefore not migrated. + #[migration_state(omit)] capability: u64, /// General Configuration Register config: u64, @@ -666,9 +667,15 @@ pub struct HPETRegisters { counter: u64, =20 /// HPET Timer N Registers + /// + /// Migrated as part of `Migratable` + #[migration_state(omit)] tn_regs: [HPETTimerRegisters; HPET_MAX_TIMERS], =20 /// Offset of main counter relative to qemu clock. + /// + /// Migrated as a subsection and therefore snapshotted into [`HPETStat= e`] + #[migration_state(omit)] pub hpet_offset: u64, } =20 @@ -702,7 +709,7 @@ fn is_timer_int_active(&self, index: usize) -> bool { pub struct HPETState { parent_obj: ParentField, iomem: MemoryRegion, - regs: BqlRefCell, + regs: Migratable>, =20 // Internal state /// Capabilities that QEMU HPET supports. @@ -728,7 +735,7 @@ pub struct HPETState { =20 /// HPET timer array managed by this timer block. #[doc(alias =3D "timer")] - timers: [HPETTimer; HPET_MAX_TIMERS], + timers: [Migratable; HPET_MAX_TIMERS], #[property(rename =3D "timers", default =3D HPET_MIN_TIMERS)] num_timers: usize, num_timers_save: BqlCell, @@ -763,9 +770,12 @@ fn init_timers(this: &mut MaybeUninit) { =20 // Initialize in two steps, to avoid calling Timer::init_full = on a // temporary that can be moved. - let timer =3D timer.write(HPETTimer::new(index.try_into().unwr= ap(), state)); + let timer =3D timer.write(Migratable::new(HPETTimer::new( + index.try_into().unwrap(), + state, + ))); // SAFETY: HPETState is pinned - let timer =3D unsafe { Pin::new_unchecked(timer) }; + let timer =3D unsafe { Pin::new_unchecked(&mut **timer) }; HPETTimer::init_timer(timer); } } @@ -1109,47 +1119,102 @@ impl ObjectImpl for HPETState { }) .build(); =20 -impl_vmstate_struct!( - HPETTimerRegisters, - VMStateDescriptionBuilder::::new() - .name(c"hpet_timer/regs") +#[derive(Default)] +pub struct HPETTimerMigration { + index: u8, + config: u64, + cmp: u64, + fsb: u64, + period: u64, + wrap_flag: u8, + qemu_timer: i64, +} + +impl ToMigrationState for HPETTimer { + type Migrated =3D HPETTimerMigration; + + fn snapshot_migration_state( + &self, + target: &mut Self::Migrated, + ) -> Result<(), migration::Infallible> { + let state =3D self.get_state(); + let regs =3D state.regs.borrow_mut(); + let tn_regs =3D ®s.tn_regs[self.index as usize]; + + target.index =3D self.index; + target.config =3D tn_regs.config; + target.cmp =3D tn_regs.cmp; + target.fsb =3D tn_regs.fsb; + target.period =3D tn_regs.period; + target.wrap_flag =3D tn_regs.wrap_flag; + self.qemu_timer + .snapshot_migration_state(&mut target.qemu_timer)?; + + Ok(()) + } + + fn restore_migrated_state_mut( + &mut self, + source: Self::Migrated, + version_id: u8, + ) -> Result<(), migration::Infallible> { + self.restore_migrated_state(source, version_id) + } +} + +impl ToMigrationStateShared for HPETTimer { + fn restore_migrated_state( + &self, + source: Self::Migrated, + version_id: u8, + ) -> Result<(), migration::Infallible> { + let state =3D self.get_state(); + let mut regs =3D state.regs.borrow_mut(); + let tn_regs =3D &mut regs.tn_regs[self.index as usize]; + + tn_regs.config =3D source.config; + tn_regs.cmp =3D source.cmp; + tn_regs.fsb =3D source.fsb; + tn_regs.period =3D source.period; + tn_regs.wrap_flag =3D source.wrap_flag; + self.qemu_timer + .restore_migrated_state(source.qemu_timer, version_id)?; + + Ok(()) + } +} + +const VMSTATE_HPET_TIMER: VMStateDescription =3D + VMStateDescriptionBuilder::::new() + .name(c"hpet_timer") .version_id(1) .minimum_version_id(1) .fields(vmstate_fields! { - vmstate_of!(HPETTimerRegisters, config), - vmstate_of!(HPETTimerRegisters, cmp), - vmstate_of!(HPETTimerRegisters, fsb), - vmstate_of!(HPETTimerRegisters, period), - vmstate_of!(HPETTimerRegisters, wrap_flag), - }) - .build() -); - -const VMSTATE_HPET_TIMER: VMStateDescription =3D - VMStateDescriptionBuilder::::new() - .name(c"hpet_timer") - .version_id(2) - .minimum_version_id(2) - .fields(vmstate_fields! { - vmstate_of!(HPETTimer, qemu_timer), + vmstate_of!(HPETTimerMigration, index), + vmstate_of!(HPETTimerMigration, config), + vmstate_of!(HPETTimerMigration, cmp), + vmstate_of!(HPETTimerMigration, fsb), + vmstate_of!(HPETTimerMigration, period), + vmstate_of!(HPETTimerMigration, wrap_flag), + vmstate_of!(HPETTimerMigration, qemu_timer), }) .build(); =20 -impl_vmstate_struct!(HPETTimer, VMSTATE_HPET_TIMER); +impl_vmstate_struct!(HPETTimerMigration, VMSTATE_HPET_TIMER); =20 const VALIDATE_TIMERS_NAME: &CStr =3D c"num_timers must match"; =20 +// HPETRegistersMigration is generated by ToMigrationState macro. impl_vmstate_struct!( - HPETRegisters, - VMStateDescriptionBuilder::::new() + HPETRegistersMigration, + VMStateDescriptionBuilder::::new() .name(c"hpet/regs") .version_id(2) .minimum_version_id(2) .fields(vmstate_fields! { - vmstate_of!(HPETRegisters, config), - vmstate_of!(HPETRegisters, int_status), - vmstate_of!(HPETRegisters, counter), - vmstate_of!(HPETRegisters, tn_regs), + vmstate_of!(HPETRegistersMigration, config), + vmstate_of!(HPETRegistersMigration, int_status), + vmstate_of!(HPETRegistersMigration, counter), }) .build() ); @@ -1157,8 +1222,8 @@ impl ObjectImpl for HPETState { const VMSTATE_HPET: VMStateDescription =3D VMStateDescriptionBuilder::::new() .name(c"hpet") - .version_id(3) - .minimum_version_id(3) + .version_id(2) + .minimum_version_id(2) .pre_save(&HPETState::pre_save) .post_load(&HPETState::post_load) .fields(vmstate_fields! { --=20 2.51.1