qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PULL 00/13] Rust, i386 changes for 2025-05-03
@ 2025-05-03  7:58 Paolo Bonzini
  2025-05-03  7:58 ` [PULL 01/13] rust/vmstate: Add support for field_exists checks Paolo Bonzini
                   ` (13 more replies)
  0 siblings, 14 replies; 16+ messages in thread
From: Paolo Bonzini @ 2025-05-03  7:58 UTC (permalink / raw)
  To: qemu-devel

The following changes since commit 5134cf9b5d3aee4475fe7e1c1c11b093731073cf:

  Merge tag 'block-pull-request' of https://gitlab.com/stefanha/qemu into staging (2025-04-30 13:34:44 -0400)

are available in the Git repository at:

  https://gitlab.com/bonzini/qemu.git tags/for-upstream

for you to fetch changes up to 03f50d7ee756eecbd4481c3008b5e01e999729c7:

  monitor: don't wake up qmp_dispatcher_co coroutine upon cleanup (2025-05-02 23:51:30 +0200)

----------------------------------------------------------------
* rust: support migration of HPET device
* target/i386/hvf: fix compilation errors
* target/i386/tcg: fix some interrupt shadow cases
* hw/char/serial: remove unused prog_if compat property
* rust: centralize config in workspace root
* monitor: fix race on exiting QEMU

----------------------------------------------------------------
Andrey Drobyshev (1):
      monitor: don't wake up qmp_dispatcher_co coroutine upon cleanup

BALATON Zoltan (1):
      hw/char/serial: Remove unused prog_if compat property

Magnus Kulke (1):
      target/i386/emulate: remove rflags leftovers

Paolo Bonzini (4):
      vmstate: support varray for vmstate_clock!
      rust: assertions: Support index field wrapped in BqlCell
      target/i386: do not trigger IRQ shadow for LSS
      target/i386: do not block singlestep for STI

Stefan Zabka (1):
      rust: centralize config in workspace root

Wei Liu (1):
      target/i386/hvf: fix a compilation error

Zhao Liu (4):
      rust/vmstate: Add support for field_exists checks
      rust/vmstate_test: Test varray with num field wrapped in BqlCell
      rust/timer: Define NANOSECONDS_PER_SECOND binding as u64
      rust/hpet: Support migration

 docs/devel/rust.rst                  |   3 +-
 hw/char/diva-gsp.c                   |   6 +-
 hw/char/serial-pci-multi.c           |   7 +-
 hw/char/serial-pci.c                 |  10 +--
 monitor/qmp.c                        |   3 +-
 target/i386/emulate/x86_decode.c     |  17 ++--
 target/i386/hvf/hvf.c                |   1 +
 target/i386/tcg/translate.c          |  33 +++++---
 target/i386/tcg/emit.c.inc           |   4 +-
 rust/Cargo.toml                      |   7 ++
 rust/hw/char/pl011/Cargo.toml        |  11 +--
 rust/hw/timer/hpet/Cargo.toml        |   9 ++-
 rust/hw/timer/hpet/src/hpet.rs       | 146 ++++++++++++++++++++++++++++++++++-
 rust/qemu-api-macros/Cargo.toml      |  11 +--
 rust/qemu-api/Cargo.toml             |  15 ++--
 rust/qemu-api/src/assertions.rs      |  25 +++---
 rust/qemu-api/src/timer.rs           |   2 +
 rust/qemu-api/src/vmstate.rs         |  83 +++++++++++---------
 rust/qemu-api/tests/vmstate_tests.rs |  41 ++++++++--
 19 files changed, 307 insertions(+), 127 deletions(-)
-- 
2.49.0



^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PULL 01/13] rust/vmstate: Add support for field_exists checks
  2025-05-03  7:58 [PULL 00/13] Rust, i386 changes for 2025-05-03 Paolo Bonzini
@ 2025-05-03  7:58 ` Paolo Bonzini
  2025-05-03  7:58 ` [PULL 02/13] vmstate: support varray for vmstate_clock! Paolo Bonzini
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2025-05-03  7:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Zhao Liu

From: Zhao Liu <zhao1.liu@intel.com>

Unfortunately, at present it's not possible to have a const
"with_exist_check" method to append test_fn after vmstate_struct (due
to error on "constant functions cannot evaluate destructors" for `F`).

Before the vmstate builder, the only way to support "test_fn" is to
extend vmstate_struct macro to add the such new optional member (and
fortunately, Rust can still parse the current expansion!).

Abstract the previous callback implementation of vmstate_validate into
a separate macro, and moves it before vmstate_struct for vmstate_struct
to call.

Note that there's no need to add any extra flag for a new test_fn added
in the VMStateField.

Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250414144943.1112885-2-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 rust/qemu-api/src/vmstate.rs | 70 +++++++++++++++++++-----------------
 1 file changed, 37 insertions(+), 33 deletions(-)

diff --git a/rust/qemu-api/src/vmstate.rs b/rust/qemu-api/src/vmstate.rs
index 1b2b12eadd6..8c4a5bee3c1 100644
--- a/rust/qemu-api/src/vmstate.rs
+++ b/rust/qemu-api/src/vmstate.rs
@@ -200,13 +200,14 @@ pub const fn vmstate_varray_flag<T: VMState>(_: PhantomData<T>) -> VMStateFlags
 /// and [`impl_vmstate_forward!`](crate::impl_vmstate_forward) help with this.
 #[macro_export]
 macro_rules! vmstate_of {
-    ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:expr)?])? $(,)?) => {
+    ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:expr)?])? $(, $test_fn:expr)? $(,)?) => {
         $crate::bindings::VMStateField {
             name: ::core::concat!(::core::stringify!($field_name), "\0")
                 .as_bytes()
                 .as_ptr() as *const ::std::os::raw::c_char,
             offset: $crate::offset_of!($struct_name, $field_name),
             $(num_offset: $crate::offset_of!($struct_name, $num),)?
+            $(field_exists: $crate::vmstate_exist_fn!($struct_name, $test_fn),)?
             // The calls to `call_func_with_field!` are the magic that
             // computes most of the VMStateField from the type of the field.
             info: $crate::info_enum_to_ref!($crate::call_func_with_field!(
@@ -435,6 +436,38 @@ macro_rules! vmstate_unused {
     }};
 }
 
+pub extern "C" fn rust_vms_test_field_exists<T, F: for<'a> FnCall<(&'a T, u8), bool>>(
+    opaque: *mut c_void,
+    version_id: c_int,
+) -> bool {
+    // SAFETY: the opaque was passed as a reference to `T`.
+    let owner: &T = unsafe { &*(opaque.cast::<T>()) };
+    let version: u8 = version_id.try_into().unwrap();
+    F::call((owner, version))
+}
+
+pub type VMSFieldExistCb = unsafe extern "C" fn(
+    opaque: *mut std::os::raw::c_void,
+    version_id: std::os::raw::c_int,
+) -> bool;
+
+#[macro_export]
+macro_rules! vmstate_exist_fn {
+    ($struct_name:ty, $test_fn:expr) => {{
+        const fn test_cb_builder__<T, F: for<'a> $crate::callbacks::FnCall<(&'a T, u8), bool>>(
+            _phantom: ::core::marker::PhantomData<F>,
+        ) -> $crate::vmstate::VMSFieldExistCb {
+            let _: () = F::ASSERT_IS_SOME;
+            $crate::vmstate::rust_vms_test_field_exists::<T, F>
+        }
+
+        const fn phantom__<T>(_: &T) -> ::core::marker::PhantomData<T> {
+            ::core::marker::PhantomData
+        }
+        Some(test_cb_builder__::<$struct_name, _>(phantom__(&$test_fn)))
+    }};
+}
+
 // FIXME: including the `vmsd` field in a `const` is not possible without
 // the const_refs_static feature (stabilized in Rust 1.83.0).  Without it,
 // it is not possible to use VMS_STRUCT in a transparent manner using
@@ -445,7 +478,7 @@ macro_rules! vmstate_unused {
 #[doc(alias = "VMSTATE_STRUCT")]
 #[macro_export]
 macro_rules! vmstate_struct {
-    ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:expr)?])?, $vmsd:expr, $type:ty $(,)?) => {
+    ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:expr)?])?, $vmsd:expr, $type:ty $(, $test_fn:expr)? $(,)?) => {
         $crate::bindings::VMStateField {
             name: ::core::concat!(::core::stringify!($field_name), "\0")
                 .as_bytes()
@@ -458,6 +491,7 @@ macro_rules! vmstate_struct {
             size: ::core::mem::size_of::<$type>(),
             flags: $crate::bindings::VMStateFlags::VMS_STRUCT,
             vmsd: $vmsd,
+            $(field_exists: $crate::vmstate_exist_fn!($struct_name, $test_fn),)?
             ..$crate::zeroable::Zeroable::ZERO
          } $(.with_varray_flag_unchecked(
                   $crate::call_func_with_field!(
@@ -514,43 +548,13 @@ macro_rules! vmstate_fields {
     }}
 }
 
-pub extern "C" fn rust_vms_test_field_exists<T, F: for<'a> FnCall<(&'a T, u8), bool>>(
-    opaque: *mut c_void,
-    version_id: c_int,
-) -> bool {
-    let owner: &T = unsafe { &*(opaque.cast::<T>()) };
-    let version: u8 = version_id.try_into().unwrap();
-    // SAFETY: the opaque was passed as a reference to `T`.
-    F::call((owner, version))
-}
-
-pub type VMSFieldExistCb = unsafe extern "C" fn(
-    opaque: *mut std::os::raw::c_void,
-    version_id: std::os::raw::c_int,
-) -> bool;
-
 #[doc(alias = "VMSTATE_VALIDATE")]
 #[macro_export]
 macro_rules! vmstate_validate {
     ($struct_name:ty, $test_name:expr, $test_fn:expr $(,)?) => {
         $crate::bindings::VMStateField {
             name: ::std::ffi::CStr::as_ptr($test_name),
-            field_exists: {
-                const fn test_cb_builder__<
-                    T,
-                    F: for<'a> $crate::callbacks::FnCall<(&'a T, u8), bool>,
-                >(
-                    _phantom: ::core::marker::PhantomData<F>,
-                ) -> $crate::vmstate::VMSFieldExistCb {
-                    let _: () = F::ASSERT_IS_SOME;
-                    $crate::vmstate::rust_vms_test_field_exists::<T, F>
-                }
-
-                const fn phantom__<T>(_: &T) -> ::core::marker::PhantomData<T> {
-                    ::core::marker::PhantomData
-                }
-                Some(test_cb_builder__::<$struct_name, _>(phantom__(&$test_fn)))
-            },
+            field_exists: $crate::vmstate_exist_fn!($struct_name, $test_fn),
             flags: $crate::bindings::VMStateFlags(
                 $crate::bindings::VMStateFlags::VMS_MUST_EXIST.0
                     | $crate::bindings::VMStateFlags::VMS_ARRAY.0,
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 02/13] vmstate: support varray for vmstate_clock!
  2025-05-03  7:58 [PULL 00/13] Rust, i386 changes for 2025-05-03 Paolo Bonzini
  2025-05-03  7:58 ` [PULL 01/13] rust/vmstate: Add support for field_exists checks Paolo Bonzini
@ 2025-05-03  7:58 ` Paolo Bonzini
  2025-05-03  7:58 ` [PULL 03/13] rust: assertions: Support index field wrapped in BqlCell Paolo Bonzini
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2025-05-03  7:58 UTC (permalink / raw)
  To: qemu-devel

Make vmstate_struct and vmstate_clock more similar; they are basically the
same thing, except for the clock case having a built-in VMStateDescription.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 rust/qemu-api/src/vmstate.rs | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/rust/qemu-api/src/vmstate.rs b/rust/qemu-api/src/vmstate.rs
index 8c4a5bee3c1..9ae97c389c1 100644
--- a/rust/qemu-api/src/vmstate.rs
+++ b/rust/qemu-api/src/vmstate.rs
@@ -507,7 +507,7 @@ macro_rules! vmstate_struct {
 #[doc(alias = "VMSTATE_CLOCK")]
 #[macro_export]
 macro_rules! vmstate_clock {
-    ($struct_name:ty, $field_name:ident) => {{
+    ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:expr)?])?) => {{
         $crate::bindings::VMStateField {
             name: ::core::concat!(::core::stringify!($field_name), "\0")
                 .as_bytes()
@@ -516,7 +516,7 @@ macro_rules! vmstate_clock {
                 $crate::assert_field_type!(
                     $struct_name,
                     $field_name,
-                    $crate::qom::Owned<$crate::qdev::Clock>
+                    $crate::qom::Owned<$crate::qdev::Clock> $(, num = $num)?
                 );
                 $crate::offset_of!($struct_name, $field_name)
             },
@@ -527,7 +527,14 @@ macro_rules! vmstate_clock {
             ),
             vmsd: unsafe { ::core::ptr::addr_of!($crate::bindings::vmstate_clock) },
             ..$crate::zeroable::Zeroable::ZERO
-        }
+         } $(.with_varray_flag_unchecked(
+                  $crate::call_func_with_field!(
+                      $crate::vmstate::vmstate_varray_flag,
+                      $struct_name,
+                      $num
+                  )
+              )
+           $(.with_varray_multiply($factor))?)?
     }};
 }
 
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 03/13] rust: assertions: Support index field wrapped in BqlCell
  2025-05-03  7:58 [PULL 00/13] Rust, i386 changes for 2025-05-03 Paolo Bonzini
  2025-05-03  7:58 ` [PULL 01/13] rust/vmstate: Add support for field_exists checks Paolo Bonzini
  2025-05-03  7:58 ` [PULL 02/13] vmstate: support varray for vmstate_clock! Paolo Bonzini
@ 2025-05-03  7:58 ` Paolo Bonzini
  2025-05-03  7:58 ` [PULL 04/13] rust/vmstate_test: Test varray with num " Paolo Bonzini
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2025-05-03  7:58 UTC (permalink / raw)
  To: qemu-devel

Currently, if the `num` field of a varray is not a numeric type, such as
being placed in a wrapper, the array variant of assert_field_type will
fail the check.

HPET currently wraps num_timers in BqlCell<>. Although BqlCell<> is not
necessary from strictly speaking, it makes sense for vmstate to respect
BqlCell.

The failure of assert_field_type is because it cannot convert BqlCell<T>
into usize for use as the index.  Use a constant 0 instead for the index,
by avoiding $(...)? and extracting the common parts of
assert_field_type! into an internal case.

Commit message based on a patch by Zhao Liu <zhao1.liu@intel.com>.

Link: https://lore.kernel.org/r/20250414144943.1112885-3-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 rust/qemu-api/src/assertions.rs | 25 +++++++++----------------
 1 file changed, 9 insertions(+), 16 deletions(-)

diff --git a/rust/qemu-api/src/assertions.rs b/rust/qemu-api/src/assertions.rs
index eb12e9499a7..a2d38c877df 100644
--- a/rust/qemu-api/src/assertions.rs
+++ b/rust/qemu-api/src/assertions.rs
@@ -78,33 +78,26 @@ fn types_must_be_equal<T, U>(_: T)
 /// ```
 #[macro_export]
 macro_rules! assert_field_type {
-    ($t:ty, $i:tt, $ti:ty) => {
+    (@internal $param_name:ident, $ti:ty, $t:ty, $($field:tt)*) => {
         const _: () = {
             #[allow(unused)]
-            fn assert_field_type(v: $t) {
-                fn types_must_be_equal<T, U>(_: T)
+            fn assert_field_type($param_name: &$t) {
+                fn types_must_be_equal<T, U>(_: &T)
                 where
                     T: $crate::assertions::EqType<Itself = U>,
                 {
                 }
-                types_must_be_equal::<_, $ti>(v.$i);
+                types_must_be_equal::<_, $ti>(&$($field)*);
             }
         };
     };
 
+    ($t:ty, $i:tt, $ti:ty) => {
+        $crate::assert_field_type!(@internal v, $ti, $t, v.$i);
+    };
+
     ($t:ty, $i:tt, $ti:ty, num = $num:ident) => {
-        const _: () = {
-            #[allow(unused)]
-            fn assert_field_type(v: $t) {
-                fn types_must_be_equal<T, U>(_: T)
-                where
-                    T: $crate::assertions::EqType<Itself = U>,
-                {
-                }
-                let index: usize = v.$num.try_into().unwrap();
-                types_must_be_equal::<_, &$ti>(&v.$i[index]);
-            }
-        };
+        $crate::assert_field_type!(@internal v, $ti, $t, v.$i[0]);
     };
 }
 
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 04/13] rust/vmstate_test: Test varray with num field wrapped in BqlCell
  2025-05-03  7:58 [PULL 00/13] Rust, i386 changes for 2025-05-03 Paolo Bonzini
                   ` (2 preceding siblings ...)
  2025-05-03  7:58 ` [PULL 03/13] rust: assertions: Support index field wrapped in BqlCell Paolo Bonzini
@ 2025-05-03  7:58 ` Paolo Bonzini
  2025-05-03  7:58 ` [PULL 05/13] rust/timer: Define NANOSECONDS_PER_SECOND binding as u64 Paolo Bonzini
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2025-05-03  7:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Zhao Liu

From: Zhao Liu <zhao1.liu@intel.com>

Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250414144943.1112885-4-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 rust/qemu-api/tests/vmstate_tests.rs | 41 ++++++++++++++++++++++------
 1 file changed, 33 insertions(+), 8 deletions(-)

diff --git a/rust/qemu-api/tests/vmstate_tests.rs b/rust/qemu-api/tests/vmstate_tests.rs
index 8b93492a689..f7a93117e1a 100644
--- a/rust/qemu-api/tests/vmstate_tests.rs
+++ b/rust/qemu-api/tests/vmstate_tests.rs
@@ -28,7 +28,7 @@
 //     - VMSTATE_VARRAY_UINT16_UNSAFE
 //     - VMSTATE_VARRAY_MULTIPLY
 #[repr(C)]
-#[derive(qemu_api_macros::offsets)]
+#[derive(Default, qemu_api_macros::offsets)]
 struct FooA {
     arr: [u8; FOO_ARRAY_MAX],
     num: u16,
@@ -147,8 +147,9 @@ fn test_vmstate_varray_multiply() {
 //     - VMSTATE_STRUCT_VARRAY_UINT8
 //     - (no C version) MULTIPLY variant of VMSTATE_STRUCT_VARRAY_UINT32
 //     - VMSTATE_ARRAY
+//     - VMSTATE_STRUCT_VARRAY_UINT8 with BqlCell wrapper & test_fn
 #[repr(C)]
-#[derive(qemu_api_macros::offsets)]
+#[derive(Default, qemu_api_macros::offsets)]
 struct FooB {
     arr_a: [FooA; FOO_ARRAY_MAX],
     num_a: u8,
@@ -158,6 +159,12 @@ struct FooB {
     val: bool,
     // FIXME: Use Timer array. Now we can't since it's hard to link savevm.c to test.
     arr_i64: [i64; FOO_ARRAY_MAX],
+    arr_a_wrap: [FooA; FOO_ARRAY_MAX],
+    num_a_wrap: BqlCell<u32>,
+}
+
+fn validate_foob(_state: &FooB, _version_id: u8) -> bool {
+    true
 }
 
 static VMSTATE_FOOB: VMStateDescription = VMStateDescription {
@@ -170,13 +177,14 @@ struct FooB {
         vmstate_struct!(FooB, arr_a[0 .. num_a], &VMSTATE_FOOA, FooA).with_version_id(1),
         vmstate_struct!(FooB, arr_a_mul[0 .. num_a_mul * 32], &VMSTATE_FOOA, FooA).with_version_id(2),
         vmstate_of!(FooB, arr_i64),
+        vmstate_struct!(FooB, arr_a_wrap[0 .. num_a_wrap], &VMSTATE_FOOA, FooA, validate_foob),
     },
     ..Zeroable::ZERO
 };
 
 #[test]
 fn test_vmstate_bool_v() {
-    let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOB.fields, 6) };
+    let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOB.fields, 7) };
 
     // 1st VMStateField ("val") in VMSTATE_FOOB (corresponding to VMSTATE_BOOL_V)
     assert_eq!(
@@ -196,7 +204,7 @@ fn test_vmstate_bool_v() {
 
 #[test]
 fn test_vmstate_uint64() {
-    let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOB.fields, 6) };
+    let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOB.fields, 7) };
 
     // 2nd VMStateField ("wrap") in VMSTATE_FOOB (corresponding to VMSTATE_U64)
     assert_eq!(
@@ -216,7 +224,7 @@ fn test_vmstate_uint64() {
 
 #[test]
 fn test_vmstate_struct_varray_uint8() {
-    let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOB.fields, 6) };
+    let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOB.fields, 7) };
 
     // 3rd VMStateField ("arr_a") in VMSTATE_FOOB (corresponding to
     // VMSTATE_STRUCT_VARRAY_UINT8)
@@ -240,7 +248,7 @@ fn test_vmstate_struct_varray_uint8() {
 
 #[test]
 fn test_vmstate_struct_varray_uint32_multiply() {
-    let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOB.fields, 6) };
+    let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOB.fields, 7) };
 
     // 4th VMStateField ("arr_a_mul") in VMSTATE_FOOB (corresponding to
     // (no C version) MULTIPLY variant of VMSTATE_STRUCT_VARRAY_UINT32)
@@ -266,7 +274,7 @@ fn test_vmstate_struct_varray_uint32_multiply() {
 
 #[test]
 fn test_vmstate_macro_array() {
-    let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOB.fields, 6) };
+    let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOB.fields, 7) };
 
     // 5th VMStateField ("arr_i64") in VMSTATE_FOOB (corresponding to
     // VMSTATE_ARRAY)
@@ -283,9 +291,26 @@ fn test_vmstate_macro_array() {
     assert_eq!(foo_fields[4].flags, VMStateFlags::VMS_ARRAY);
     assert!(foo_fields[4].vmsd.is_null());
     assert!(foo_fields[4].field_exists.is_none());
+}
+
+#[test]
+fn test_vmstate_struct_varray_uint8_wrapper() {
+    let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOB.fields, 7) };
+    let mut foo_b: FooB = Default::default();
+    let foo_b_p = std::ptr::addr_of_mut!(foo_b).cast::<c_void>();
+
+    // 6th VMStateField ("arr_a_wrap") in VMSTATE_FOOB (corresponding to
+    // VMSTATE_STRUCT_VARRAY_UINT8). Other fields are checked in
+    // test_vmstate_struct_varray_uint8.
+    assert_eq!(
+        unsafe { CStr::from_ptr(foo_fields[5].name) }.to_bytes_with_nul(),
+        b"arr_a_wrap\0"
+    );
+    assert_eq!(foo_fields[5].num_offset, 228);
+    assert!(unsafe { foo_fields[5].field_exists.unwrap()(foo_b_p, 0) });
 
     // The last VMStateField in VMSTATE_FOOB.
-    assert_eq!(foo_fields[5].flags, VMStateFlags::VMS_END);
+    assert_eq!(foo_fields[6].flags, VMStateFlags::VMS_END);
 }
 
 // =========================== Test VMSTATE_FOOC ===========================
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 05/13] rust/timer: Define NANOSECONDS_PER_SECOND binding as u64
  2025-05-03  7:58 [PULL 00/13] Rust, i386 changes for 2025-05-03 Paolo Bonzini
                   ` (3 preceding siblings ...)
  2025-05-03  7:58 ` [PULL 04/13] rust/vmstate_test: Test varray with num " Paolo Bonzini
@ 2025-05-03  7:58 ` Paolo Bonzini
  2025-05-03  7:58 ` [PULL 06/13] rust/hpet: Support migration Paolo Bonzini
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2025-05-03  7:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Zhao Liu

From: Zhao Liu <zhao1.liu@intel.com>

NANOSECONDS_PER_SECOND is often used in operations with get_ns(), which
currently returns a u64.

Therefore, define a new NANOSECONDS_PER_SECOND binding is with u64 type
to eliminate unnecessary type conversions (from u32 to u64).

Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250414144943.1112885-6-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 rust/qemu-api/src/timer.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/rust/qemu-api/src/timer.rs b/rust/qemu-api/src/timer.rs
index f0b04ef95d7..e769f8bc910 100644
--- a/rust/qemu-api/src/timer.rs
+++ b/rust/qemu-api/src/timer.rs
@@ -121,3 +121,5 @@ pub fn get_ns(&self) -> u64 {
 pub const CLOCK_VIRTUAL: ClockType = ClockType {
     id: QEMUClockType::QEMU_CLOCK_VIRTUAL,
 };
+
+pub const NANOSECONDS_PER_SECOND: u64 = 1000000000;
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 06/13] rust/hpet: Support migration
  2025-05-03  7:58 [PULL 00/13] Rust, i386 changes for 2025-05-03 Paolo Bonzini
                   ` (4 preceding siblings ...)
  2025-05-03  7:58 ` [PULL 05/13] rust/timer: Define NANOSECONDS_PER_SECOND binding as u64 Paolo Bonzini
@ 2025-05-03  7:58 ` Paolo Bonzini
  2025-05-03  7:58 ` [PULL 07/13] target/i386/emulate: remove rflags leftovers Paolo Bonzini
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2025-05-03  7:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Zhao Liu

From: Zhao Liu <zhao1.liu@intel.com>

Based on commit 1433e38cc8 ("hpet: do not overwrite properties on
post_load"), add the basic migration support to Rust HPET.

The current migration implementation introduces multiple unsafe
callbacks. Before the vmstate builder, one possible cleanup approach is
to wrap callbacks in the vmstate binding using a method similar to the
vmstate_exist_fn macro.

However, this approach would also create a lot of repetitive code (since
vmstate has so many callbacks: pre_load, post_load, pre_save, post_save,
needed and dev_unplug_pending). Although it would be cleaner, it would
somewhat deviate from the path of the vmstate builder.

Therefore, firstly focus on completing the functionality of HPET, and
those current unsafe callbacks can at least clearly indicate the needed
functionality of vmstate. The next step is to consider refactoring
vmstate to move towards the vmstate builder direction.

Additionally, update rust.rst about Rust HPET can support migration.

Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250414144943.1112885-9-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 docs/devel/rust.rst            |   3 +-
 rust/hw/timer/hpet/src/hpet.rs | 146 ++++++++++++++++++++++++++++++++-
 2 files changed, 146 insertions(+), 3 deletions(-)

diff --git a/docs/devel/rust.rst b/docs/devel/rust.rst
index 88bdec1eb28..3cc2841d4d1 100644
--- a/docs/devel/rust.rst
+++ b/docs/devel/rust.rst
@@ -153,8 +153,7 @@ QEMU includes four crates:
 
 .. [#issues] The ``pl011`` crate is synchronized with ``hw/char/pl011.c``
    as of commit 02b1f7f61928.  The ``hpet`` crate is synchronized as of
-   commit f32352ff9e.  Both are lacking tracing functionality; ``hpet``
-   is also lacking support for migration.
+   commit 1433e38cc8.  Both are lacking tracing functionality.
 
 This section explains how to work with them.
 
diff --git a/rust/hw/timer/hpet/src/hpet.rs b/rust/hw/timer/hpet/src/hpet.rs
index cbd2ed4f6bf..12de2ba59a1 100644
--- a/rust/hw/timer/hpet/src/hpet.rs
+++ b/rust/hw/timer/hpet/src/hpet.rs
@@ -4,6 +4,7 @@
 
 use std::{
     ffi::CStr,
+    os::raw::{c_int, c_void},
     pin::Pin,
     ptr::{addr_of_mut, null_mut, NonNull},
     slice::from_ref,
@@ -25,7 +26,10 @@
     qom::{ObjectImpl, ObjectType, ParentField},
     qom_isa,
     sysbus::{SysBusDevice, SysBusDeviceImpl},
-    timer::{Timer, CLOCK_VIRTUAL},
+    timer::{Timer, CLOCK_VIRTUAL, NANOSECONDS_PER_SECOND},
+    vmstate::VMStateDescription,
+    vmstate_fields, vmstate_of, vmstate_struct, vmstate_subsections, vmstate_validate,
+    zeroable::Zeroable,
 };
 
 use crate::fw_cfg::HPETFwConfig;
@@ -561,6 +565,7 @@ pub struct HPETState {
     #[doc(alias = "timer")]
     timers: [BqlRefCell<HPETTimer>; HPET_MAX_TIMERS as usize],
     num_timers: BqlCell<u8>,
+    num_timers_save: BqlCell<u8>,
 
     /// Instance id (HPET timer block ID).
     hpet_id: BqlCell<usize>,
@@ -839,6 +844,49 @@ fn write(&self, addr: hwaddr, value: u64, size: u32) {
             }
         }
     }
+
+    fn pre_save(&self) -> i32 {
+        if self.is_hpet_enabled() {
+            self.counter.set(self.get_ticks());
+        }
+
+        /*
+         * The number of timers must match on source and destination, but it was
+         * also added to the migration stream.  Check that it matches the value
+         * that was configured.
+         */
+        self.num_timers_save.set(self.num_timers.get());
+        0
+    }
+
+    fn post_load(&self, _version_id: u8) -> i32 {
+        for timer in self.timers.iter().take(self.get_num_timers()) {
+            let mut t = timer.borrow_mut();
+
+            t.cmp64 = t.calculate_cmp64(t.get_state().counter.get(), t.cmp);
+            t.last = CLOCK_VIRTUAL.get_ns() - NANOSECONDS_PER_SECOND;
+        }
+
+        // Recalculate the offset between the main counter and guest time
+        if !self.hpet_offset_saved {
+            self.hpet_offset
+                .set(ticks_to_ns(self.counter.get()) - CLOCK_VIRTUAL.get_ns());
+        }
+
+        0
+    }
+
+    fn is_rtc_irq_level_needed(&self) -> bool {
+        self.rtc_irq_level.get() != 0
+    }
+
+    fn is_offset_needed(&self) -> bool {
+        self.is_hpet_enabled() && self.hpet_offset_saved
+    }
+
+    fn validate_num_timers(&self, _version_id: u8) -> bool {
+        self.num_timers.get() == self.num_timers_save.get()
+    }
 }
 
 qom_isa!(HPETState: SysBusDevice, DeviceState, Object);
@@ -895,11 +943,107 @@ impl ObjectImpl for HPETState {
     ),
 }
 
+unsafe extern "C" fn hpet_rtc_irq_level_needed(opaque: *mut c_void) -> bool {
+    // SAFETY:
+    // the pointer is convertible to a reference
+    let state: &HPETState = unsafe { NonNull::new(opaque.cast::<HPETState>()).unwrap().as_ref() };
+    state.is_rtc_irq_level_needed()
+}
+
+unsafe extern "C" fn hpet_offset_needed(opaque: *mut c_void) -> bool {
+    // SAFETY:
+    // the pointer is convertible to a reference
+    let state: &HPETState = unsafe { NonNull::new(opaque.cast::<HPETState>()).unwrap().as_ref() };
+    state.is_offset_needed()
+}
+
+unsafe extern "C" fn hpet_pre_save(opaque: *mut c_void) -> c_int {
+    // SAFETY:
+    // the pointer is convertible to a reference
+    let state: &mut HPETState =
+        unsafe { NonNull::new(opaque.cast::<HPETState>()).unwrap().as_mut() };
+    state.pre_save() as c_int
+}
+
+unsafe extern "C" fn hpet_post_load(opaque: *mut c_void, version_id: c_int) -> c_int {
+    // SAFETY:
+    // the pointer is convertible to a reference
+    let state: &mut HPETState =
+        unsafe { NonNull::new(opaque.cast::<HPETState>()).unwrap().as_mut() };
+    let version: u8 = version_id.try_into().unwrap();
+    state.post_load(version) as c_int
+}
+
+static VMSTATE_HPET_RTC_IRQ_LEVEL: VMStateDescription = VMStateDescription {
+    name: c_str!("hpet/rtc_irq_level").as_ptr(),
+    version_id: 1,
+    minimum_version_id: 1,
+    needed: Some(hpet_rtc_irq_level_needed),
+    fields: vmstate_fields! {
+        vmstate_of!(HPETState, rtc_irq_level),
+    },
+    ..Zeroable::ZERO
+};
+
+static VMSTATE_HPET_OFFSET: VMStateDescription = VMStateDescription {
+    name: c_str!("hpet/offset").as_ptr(),
+    version_id: 1,
+    minimum_version_id: 1,
+    needed: Some(hpet_offset_needed),
+    fields: vmstate_fields! {
+        vmstate_of!(HPETState, hpet_offset),
+    },
+    ..Zeroable::ZERO
+};
+
+static VMSTATE_HPET_TIMER: VMStateDescription = VMStateDescription {
+    name: c_str!("hpet_timer").as_ptr(),
+    version_id: 1,
+    minimum_version_id: 1,
+    fields: vmstate_fields! {
+        vmstate_of!(HPETTimer, index),
+        vmstate_of!(HPETTimer, config),
+        vmstate_of!(HPETTimer, cmp),
+        vmstate_of!(HPETTimer, fsb),
+        vmstate_of!(HPETTimer, period),
+        vmstate_of!(HPETTimer, wrap_flag),
+        vmstate_of!(HPETTimer, qemu_timer),
+    },
+    ..Zeroable::ZERO
+};
+
+const VALIDATE_TIMERS_NAME: &CStr = c_str!("num_timers must match");
+
+static VMSTATE_HPET: VMStateDescription = VMStateDescription {
+    name: c_str!("hpet").as_ptr(),
+    version_id: 2,
+    minimum_version_id: 1,
+    pre_save: Some(hpet_pre_save),
+    post_load: Some(hpet_post_load),
+    fields: vmstate_fields! {
+        vmstate_of!(HPETState, config),
+        vmstate_of!(HPETState, int_status),
+        vmstate_of!(HPETState, counter),
+        vmstate_of!(HPETState, num_timers_save).with_version_id(2),
+        vmstate_validate!(HPETState, VALIDATE_TIMERS_NAME, HPETState::validate_num_timers),
+        vmstate_struct!(HPETState, timers[0 .. num_timers], &VMSTATE_HPET_TIMER, BqlRefCell<HPETTimer>, HPETState::validate_num_timers).with_version_id(0),
+    },
+    subsections: vmstate_subsections! {
+        VMSTATE_HPET_RTC_IRQ_LEVEL,
+        VMSTATE_HPET_OFFSET,
+    },
+    ..Zeroable::ZERO
+};
+
 impl DeviceImpl for HPETState {
     fn properties() -> &'static [Property] {
         &HPET_PROPERTIES
     }
 
+    fn vmsd() -> Option<&'static VMStateDescription> {
+        Some(&VMSTATE_HPET)
+    }
+
     const REALIZE: Option<fn(&Self)> = Some(Self::realize);
 }
 
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 07/13] target/i386/emulate: remove rflags leftovers
  2025-05-03  7:58 [PULL 00/13] Rust, i386 changes for 2025-05-03 Paolo Bonzini
                   ` (5 preceding siblings ...)
  2025-05-03  7:58 ` [PULL 06/13] rust/hpet: Support migration Paolo Bonzini
@ 2025-05-03  7:58 ` Paolo Bonzini
  2025-05-03  7:58 ` [PULL 08/13] target/i386/hvf: fix a compilation error Paolo Bonzini
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2025-05-03  7:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Magnus Kulke

From: Magnus Kulke <magnuskulke@linux.microsoft.com>

Fixes: c901905ea670 ("target/i386/emulate: remove flags_mask")

In c901905ea670 rflags have been removed from `x86_decode`, but there
were some leftovers.

Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
Link: https://lore.kernel.org/r/20250429093319.5010-1-magnuskulke@linux.microsoft.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/emulate/x86_decode.c | 17 ++++++-----------
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/target/i386/emulate/x86_decode.c b/target/i386/emulate/x86_decode.c
index 7fee2196878..7efa2f570ea 100644
--- a/target/i386/emulate/x86_decode.c
+++ b/target/i386/emulate/x86_decode.c
@@ -1408,7 +1408,7 @@ struct decode_tbl _2op_inst[] = {
 };
 
 struct decode_x87_tbl invl_inst_x87 = {0x0, 0, 0, 0, 0, false, false, NULL,
-                                       NULL, decode_invalid, 0};
+                                       NULL, decode_invalid};
 
 struct decode_x87_tbl _x87_inst[] = {
     {0xd8, 0, 3, X86_DECODE_CMD_FADD, 10, false, false,
@@ -1456,8 +1456,7 @@ struct decode_x87_tbl _x87_inst[] = {
      decode_x87_modrm_st0, NULL, decode_d9_4},
     {0xd9, 4, 0, X86_DECODE_CMD_INVL, 4, false, false,
      decode_x87_modrm_bytep, NULL, NULL},
-    {0xd9, 5, 3, X86_DECODE_CMD_FLDxx, 10, false, false, NULL, NULL, NULL,
-     RFLAGS_MASK_NONE},
+    {0xd9, 5, 3, X86_DECODE_CMD_FLDxx, 10, false, false, NULL, NULL, NULL},
     {0xd9, 5, 0, X86_DECODE_CMD_FLDCW, 2, false, false,
      decode_x87_modrm_bytep, NULL, NULL},
 
@@ -1478,20 +1477,17 @@ struct decode_x87_tbl _x87_inst[] = {
      decode_x87_modrm_st0, NULL},
     {0xda, 3, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0,
      decode_x87_modrm_st0, NULL},
-    {0xda, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL,
-     RFLAGS_MASK_NONE},
+    {0xda, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL},
     {0xda, 4, 0, X86_DECODE_CMD_FSUB, 4, false, false, decode_x87_modrm_st0,
      decode_x87_modrm_intp, NULL},
     {0xda, 5, 3, X86_DECODE_CMD_FUCOM, 10, false, true, decode_x87_modrm_st0,
      decode_decode_x87_modrm_st0, NULL},
     {0xda, 5, 0, X86_DECODE_CMD_FSUB, 4, true, false, decode_x87_modrm_st0,
      decode_x87_modrm_intp, NULL},
-    {0xda, 6, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL,
-     RFLAGS_MASK_NONE},
+    {0xda, 6, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL},
     {0xda, 6, 0, X86_DECODE_CMD_FDIV, 4, false, false, decode_x87_modrm_st0,
      decode_x87_modrm_intp, NULL},
-    {0xda, 7, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL,
-     RFLAGS_MASK_NONE},
+    {0xda, 7, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL},
     {0xda, 7, 0, X86_DECODE_CMD_FDIV, 4, true, false, decode_x87_modrm_st0,
      decode_x87_modrm_intp, NULL},
 
@@ -1511,8 +1507,7 @@ struct decode_x87_tbl _x87_inst[] = {
      decode_x87_modrm_intp, NULL, NULL},
     {0xdb, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL,
      decode_db_4},
-    {0xdb, 4, 0, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL,
-     RFLAGS_MASK_NONE},
+    {0xdb, 4, 0, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL},
     {0xdb, 5, 3, X86_DECODE_CMD_FUCOMI, 10, false, false,
      decode_x87_modrm_st0, decode_x87_modrm_st0, NULL},
     {0xdb, 5, 0, X86_DECODE_CMD_FLD, 10, false, false,
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 08/13] target/i386/hvf: fix a compilation error
  2025-05-03  7:58 [PULL 00/13] Rust, i386 changes for 2025-05-03 Paolo Bonzini
                   ` (6 preceding siblings ...)
  2025-05-03  7:58 ` [PULL 07/13] target/i386/emulate: remove rflags leftovers Paolo Bonzini
@ 2025-05-03  7:58 ` Paolo Bonzini
  2025-05-03  7:58 ` [PULL 09/13] target/i386: do not trigger IRQ shadow for LSS Paolo Bonzini
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2025-05-03  7:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Wei Liu

From: Wei Liu <wei.liu@kernel.org>

Include exec/target_page.h to fix the following build error.

x86_64-softmmu.a.p/target_i386_hvf_hvf.c.o -c ../target/i386/hvf/hvf.c
../target/i386/hvf/hvf.c:139:49: error: use of undeclared identifier 'TARGET_PAGE_SIZE'
  139 |             uint64_t dirty_page_start = gpa & ~(TARGET_PAGE_SIZE - 1u);
      |                                                 ^
../target/i386/hvf/hvf.c:141:45: error: use of undeclared identifier 'TARGET_PAGE_SIZE'
  141 |             hv_vm_protect(dirty_page_start, TARGET_PAGE_SIZE,
      |                                             ^

Signed-off-by: Wei Liu <wei.liu@kernel.org>
Link: https://lore.kernel.org/r/aBBws1ikCDfyC0RI@liuwe-devbox-ubuntu-v2.tail21d00.ts.net
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/hvf/hvf.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index 23ebf2550ac..99e37a33e50 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -76,6 +76,7 @@
 #include "qemu/main-loop.h"
 #include "qemu/accel.h"
 #include "target/i386/cpu.h"
+#include "exec/target_page.h"
 
 static Error *invtsc_mig_blocker;
 
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 09/13] target/i386: do not trigger IRQ shadow for LSS
  2025-05-03  7:58 [PULL 00/13] Rust, i386 changes for 2025-05-03 Paolo Bonzini
                   ` (7 preceding siblings ...)
  2025-05-03  7:58 ` [PULL 08/13] target/i386/hvf: fix a compilation error Paolo Bonzini
@ 2025-05-03  7:58 ` Paolo Bonzini
  2025-05-06 19:58   ` Michael Tokarev
  2025-05-03  7:58 ` [PULL 10/13] target/i386: do not block singlestep for STI Paolo Bonzini
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 16+ messages in thread
From: Paolo Bonzini @ 2025-05-03  7:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable

Because LSS need not trigger an IRQ shadow, gen_movl_seg can't just use
the destination register to decide whether to inhibit IRQs.  Add an
argument.

Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/tcg/translate.c | 27 ++++++++++++++++-----------
 target/i386/tcg/emit.c.inc  |  4 ++--
 2 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 8a641951cd1..a4e935b043b 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2026,27 +2026,32 @@ static void gen_op_movl_seg_real(DisasContext *s, X86Seg seg_reg, TCGv seg)
 
 /* move SRC to seg_reg and compute if the CPU state may change. Never
    call this function with seg_reg == R_CS */
-static void gen_movl_seg(DisasContext *s, X86Seg seg_reg, TCGv src)
+static void gen_movl_seg(DisasContext *s, X86Seg seg_reg, TCGv src, bool inhibit_irq)
 {
     if (PE(s) && !VM86(s)) {
         TCGv_i32 sel = tcg_temp_new_i32();
 
         tcg_gen_trunc_tl_i32(sel, src);
         gen_helper_load_seg(tcg_env, tcg_constant_i32(seg_reg), sel);
-        /* abort translation because the addseg value may change or
-           because ss32 may change. For R_SS, translation must always
-           stop as a special handling must be done to disable hardware
-           interrupts for the next instruction */
-        if (seg_reg == R_SS) {
-            s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
-        } else if (CODE32(s) && seg_reg < R_FS) {
+
+        /* For move to DS/ES/SS, the addseg or ss32 flags may change.  */
+        if (CODE32(s) && seg_reg < R_FS) {
             s->base.is_jmp = DISAS_EOB_NEXT;
         }
     } else {
         gen_op_movl_seg_real(s, seg_reg, src);
-        if (seg_reg == R_SS) {
-            s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
-        }
+    }
+
+    /*
+     * For MOV or POP to SS (but not LSS) translation must always
+     * stop as a special handling must be done to disable hardware
+     * interrupts for the next instruction.
+     *
+     * DISAS_EOB_INHIBIT_IRQ is a superset of DISAS_EOB_NEXT which
+     * might have been set above.
+     */
+    if (inhibit_irq) {
+        s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
     }
 }
 
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index e3166e70a5b..1a7fab9333a 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -342,7 +342,7 @@ static void gen_writeback(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv
         break;
     case X86_OP_SEG:
         /* Note that gen_movl_seg takes care of interrupt shadow and TF.  */
-        gen_movl_seg(s, op->n, s->T0);
+        gen_movl_seg(s, op->n, v, op->n == R_SS);
         break;
     case X86_OP_INT:
         if (op->has_ea) {
@@ -2382,7 +2382,7 @@ static void gen_lxx_seg(DisasContext *s, X86DecodedInsn *decode, int seg)
     gen_op_ld_v(s, MO_16, s->T1, s->A0);
 
     /* load the segment here to handle exceptions properly */
-    gen_movl_seg(s, seg, s->T1);
+    gen_movl_seg(s, seg, s->T1, false);
 }
 
 static void gen_LDS(DisasContext *s, X86DecodedInsn *decode)
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 10/13] target/i386: do not block singlestep for STI
  2025-05-03  7:58 [PULL 00/13] Rust, i386 changes for 2025-05-03 Paolo Bonzini
                   ` (8 preceding siblings ...)
  2025-05-03  7:58 ` [PULL 09/13] target/i386: do not trigger IRQ shadow for LSS Paolo Bonzini
@ 2025-05-03  7:58 ` Paolo Bonzini
  2025-05-03  7:58 ` [PULL 11/13] hw/char/serial: Remove unused prog_if compat property Paolo Bonzini
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2025-05-03  7:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable

STI will trigger a singlestep exception even if it has inhibit-IRQ
behavior.  Do not suppress single-step for all IRQ-inhibiting
instructions, instead special case MOV SS and POP SS.

Cc: qemu-stable@nongnu.org
Fixes: f0f0136abba ("target/i386: no single-step exception after MOV or POP SS", 2024-05-25)
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/tcg/translate.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index a4e935b043b..ed43c95c1d9 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2047,11 +2047,15 @@ static void gen_movl_seg(DisasContext *s, X86Seg seg_reg, TCGv src, bool inhibit
      * stop as a special handling must be done to disable hardware
      * interrupts for the next instruction.
      *
+     * This is the last instruction, so it's okay to overwrite
+     * HF_TF_MASK; the next TB will start with the flag set.
+     *
      * DISAS_EOB_INHIBIT_IRQ is a superset of DISAS_EOB_NEXT which
      * might have been set above.
      */
     if (inhibit_irq) {
         s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
+        s->flags &= ~HF_TF_MASK;
     }
 }
 
@@ -2302,7 +2306,7 @@ gen_eob(DisasContext *s, int mode)
     if (mode == DISAS_EOB_RECHECK_TF) {
         gen_helper_rechecking_single_step(tcg_env);
         tcg_gen_exit_tb(NULL, 0);
-    } else if ((s->flags & HF_TF_MASK) && mode != DISAS_EOB_INHIBIT_IRQ) {
+    } else if (s->flags & HF_TF_MASK) {
         gen_helper_single_step(tcg_env);
     } else if (mode == DISAS_JUMP &&
                /* give irqs a chance to happen */
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 11/13] hw/char/serial: Remove unused prog_if compat property
  2025-05-03  7:58 [PULL 00/13] Rust, i386 changes for 2025-05-03 Paolo Bonzini
                   ` (9 preceding siblings ...)
  2025-05-03  7:58 ` [PULL 10/13] target/i386: do not block singlestep for STI Paolo Bonzini
@ 2025-05-03  7:58 ` Paolo Bonzini
  2025-05-03  7:58 ` [PULL 12/13] rust: centralize config in workspace root Paolo Bonzini
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2025-05-03  7:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: BALATON Zoltan, Philippe Mathieu-Daudé, Helge Deller

From: BALATON Zoltan <balaton@eik.bme.hu>

This property was added to preserve previous value when this was fixed
in version 2.1 but the last machine using it was already removed when
adding diva-gsp leaving this property unused and unnecessary.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Helge Deller <deller@gmx.de>
Link: https://lore.kernel.org/r/20250502095524.DE1F355D264@zero.eik.bme.hu
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/char/diva-gsp.c         |  6 ++----
 hw/char/serial-pci-multi.c |  7 ++-----
 hw/char/serial-pci.c       | 10 ++--------
 3 files changed, 6 insertions(+), 17 deletions(-)

diff --git a/hw/char/diva-gsp.c b/hw/char/diva-gsp.c
index 60f933191d2..e1f0713cb79 100644
--- a/hw/char/diva-gsp.c
+++ b/hw/char/diva-gsp.c
@@ -51,7 +51,6 @@ typedef struct PCIDivaSerialState {
     SerialState  state[PCI_SERIAL_MAX_PORTS];
     uint32_t     level[PCI_SERIAL_MAX_PORTS];
     qemu_irq     *irqs;
-    uint8_t      prog_if;
     bool         disable;
 } PCIDivaSerialState;
 
@@ -124,8 +123,8 @@ static void diva_pci_realize(PCIDevice *dev, Error **errp)
     size_t i, offset = 0;
     size_t portmask = di.omask;
 
-    pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
-    pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
+    pci->dev.config[PCI_CLASS_PROG] = 2; /* 16550 compatible */
+    pci->dev.config[PCI_INTERRUPT_PIN] = 1;
     memory_region_init(&pci->membar, OBJECT(pci), "serial_ports", 4096);
     pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &pci->membar);
     pci->irqs = qemu_allocate_irqs(multi_serial_irq_mux, pci, di.nports);
@@ -178,7 +177,6 @@ static const Property diva_serial_properties[] = {
     DEFINE_PROP_CHR("chardev2",  PCIDivaSerialState, state[1].chr),
     DEFINE_PROP_CHR("chardev3",  PCIDivaSerialState, state[2].chr),
     DEFINE_PROP_CHR("chardev4",  PCIDivaSerialState, state[3].chr),
-    DEFINE_PROP_UINT8("prog_if",  PCIDivaSerialState, prog_if, 0x02),
     DEFINE_PROP_UINT32("subvendor", PCIDivaSerialState, subvendor,
                                     PCI_DEVICE_ID_HP_DIVA_TOSCA1),
 };
diff --git a/hw/char/serial-pci-multi.c b/hw/char/serial-pci-multi.c
index fb184c2e6dc..13df272691a 100644
--- a/hw/char/serial-pci-multi.c
+++ b/hw/char/serial-pci-multi.c
@@ -46,7 +46,6 @@ typedef struct PCIMultiSerialState {
     SerialState  state[PCI_SERIAL_MAX_PORTS];
     uint32_t     level[PCI_SERIAL_MAX_PORTS];
     IRQState     irqs[PCI_SERIAL_MAX_PORTS];
-    uint8_t      prog_if;
 } PCIMultiSerialState;
 
 static void multi_serial_pci_exit(PCIDevice *dev)
@@ -97,8 +96,8 @@ static void multi_serial_pci_realize(PCIDevice *dev, Error **errp)
     SerialState *s;
     size_t i, nports = multi_serial_get_port_count(pc);
 
-    pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
-    pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
+    pci->dev.config[PCI_CLASS_PROG] = 2; /* 16550 compatible */
+    pci->dev.config[PCI_INTERRUPT_PIN] = 1;
     memory_region_init(&pci->iobar, OBJECT(pci), "multiserial", 8 * nports);
     pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->iobar);
 
@@ -133,7 +132,6 @@ static const VMStateDescription vmstate_pci_multi_serial = {
 static const Property multi_2x_serial_pci_properties[] = {
     DEFINE_PROP_CHR("chardev1",  PCIMultiSerialState, state[0].chr),
     DEFINE_PROP_CHR("chardev2",  PCIMultiSerialState, state[1].chr),
-    DEFINE_PROP_UINT8("prog_if",  PCIMultiSerialState, prog_if, 0x02),
 };
 
 static const Property multi_4x_serial_pci_properties[] = {
@@ -141,7 +139,6 @@ static const Property multi_4x_serial_pci_properties[] = {
     DEFINE_PROP_CHR("chardev2",  PCIMultiSerialState, state[1].chr),
     DEFINE_PROP_CHR("chardev3",  PCIMultiSerialState, state[2].chr),
     DEFINE_PROP_CHR("chardev4",  PCIMultiSerialState, state[3].chr),
-    DEFINE_PROP_UINT8("prog_if",  PCIMultiSerialState, prog_if, 0x02),
 };
 
 static void multi_2x_serial_pci_class_initfn(ObjectClass *klass,
diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c
index 8707e819144..46efabc4cbe 100644
--- a/hw/char/serial-pci.c
+++ b/hw/char/serial-pci.c
@@ -38,7 +38,6 @@
 struct PCISerialState {
     PCIDevice dev;
     SerialState state;
-    uint8_t prog_if;
 };
 
 #define TYPE_PCI_SERIAL "pci-serial"
@@ -53,8 +52,8 @@ static void serial_pci_realize(PCIDevice *dev, Error **errp)
         return;
     }
 
-    pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
-    pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
+    pci->dev.config[PCI_CLASS_PROG] = 2; /* 16550 compatible */
+    pci->dev.config[PCI_INTERRUPT_PIN] = 1;
     s->irq = pci_allocate_irq(&pci->dev);
 
     memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, "serial", 8);
@@ -81,10 +80,6 @@ static const VMStateDescription vmstate_pci_serial = {
     }
 };
 
-static const Property serial_pci_properties[] = {
-    DEFINE_PROP_UINT8("prog_if",  PCISerialState, prog_if, 0x02),
-};
-
 static void serial_pci_class_initfn(ObjectClass *klass, const void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -96,7 +91,6 @@ static void serial_pci_class_initfn(ObjectClass *klass, const void *data)
     pc->revision = 1;
     pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
     dc->vmsd = &vmstate_pci_serial;
-    device_class_set_props(dc, serial_pci_properties);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 }
 
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 12/13] rust: centralize config in workspace root
  2025-05-03  7:58 [PULL 00/13] Rust, i386 changes for 2025-05-03 Paolo Bonzini
                   ` (10 preceding siblings ...)
  2025-05-03  7:58 ` [PULL 11/13] hw/char/serial: Remove unused prog_if compat property Paolo Bonzini
@ 2025-05-03  7:58 ` Paolo Bonzini
  2025-05-03  7:58 ` [PULL 13/13] monitor: don't wake up qmp_dispatcher_co coroutine upon cleanup Paolo Bonzini
  2025-05-06 13:58 ` [PULL 00/13] Rust, i386 changes for 2025-05-03 Stefan Hajnoczi
  13 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2025-05-03  7:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Zabka

From: Stefan Zabka <git@zabka.it>

This commit bundles common config option in the workspace
root and applies them through <config>.workspace = true

Signed-off-by: Stefan Zabka <git@zabka.it>
Link: https://lore.kernel.org/r/20250502212748.124953-1-git@zabka.it
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 rust/Cargo.toml                 |  7 +++++++
 rust/hw/char/pl011/Cargo.toml   | 11 ++++++-----
 rust/hw/timer/hpet/Cargo.toml   |  9 ++++++---
 rust/qemu-api-macros/Cargo.toml | 11 ++++++-----
 rust/qemu-api/Cargo.toml        | 15 +++++++--------
 5 files changed, 32 insertions(+), 21 deletions(-)

diff --git a/rust/Cargo.toml b/rust/Cargo.toml
index ab1185a8143..5ace47c69be 100644
--- a/rust/Cargo.toml
+++ b/rust/Cargo.toml
@@ -7,6 +7,13 @@ members = [
     "hw/timer/hpet",
 ]
 
+[workspace.package]
+edition = "2021"
+homepage = "https://www.qemu.org"
+license = "GPL-2.0-or-later"
+repository = "https://gitlab.com/qemu-project/qemu/"
+rust-version = "1.63.0"
+
 [workspace.lints.rust]
 unexpected_cfgs = { level = "deny", check-cfg = [
     'cfg(MESON)', 'cfg(HAVE_GLIB_WITH_ALIGNED_ALLOC)',
diff --git a/rust/hw/char/pl011/Cargo.toml b/rust/hw/char/pl011/Cargo.toml
index f2296cad58b..a1f431ab4a3 100644
--- a/rust/hw/char/pl011/Cargo.toml
+++ b/rust/hw/char/pl011/Cargo.toml
@@ -1,15 +1,16 @@
 [package]
 name = "pl011"
 version = "0.1.0"
-edition = "2021"
 authors = ["Manos Pitsidianakis <manos.pitsidianakis@linaro.org>"]
-license = "GPL-2.0-or-later"
 description = "pl011 device model for QEMU"
 resolver = "2"
 publish = false
-keywords = []
-categories = []
-rust-version = "1.63.0"
+
+edition.workspace = true
+homepage.workspace = true
+license.workspace = true
+repository.workspace = true
+rust-version.workspace = true
 
 [lib]
 crate-type = ["staticlib"]
diff --git a/rust/hw/timer/hpet/Cargo.toml b/rust/hw/timer/hpet/Cargo.toml
index 147f216e725..6f075027843 100644
--- a/rust/hw/timer/hpet/Cargo.toml
+++ b/rust/hw/timer/hpet/Cargo.toml
@@ -1,11 +1,14 @@
 [package]
 name = "hpet"
 version = "0.1.0"
-edition = "2021"
 authors = ["Zhao Liu <zhao1.liu@intel.com>"]
-license = "GPL-2.0-or-later"
 description = "IA-PC High Precision Event Timer emulation in Rust"
-rust-version = "1.63.0"
+
+edition.workspace = true
+homepage.workspace = true
+license.workspace = true
+repository.workspace = true
+rust-version.workspace = true
 
 [lib]
 crate-type = ["staticlib"]
diff --git a/rust/qemu-api-macros/Cargo.toml b/rust/qemu-api-macros/Cargo.toml
index 89dee1cfb39..0cd40c8e168 100644
--- a/rust/qemu-api-macros/Cargo.toml
+++ b/rust/qemu-api-macros/Cargo.toml
@@ -1,15 +1,16 @@
 [package]
 name = "qemu_api_macros"
 version = "0.1.0"
-edition = "2021"
 authors = ["Manos Pitsidianakis <manos.pitsidianakis@linaro.org>"]
-license = "GPL-2.0-or-later"
 description = "Rust bindings for QEMU - Utility macros"
 resolver = "2"
 publish = false
-keywords = []
-categories = []
-rust-version = "1.63.0"
+
+edition.workspace = true
+homepage.workspace = true
+license.workspace = true
+repository.workspace = true
+rust-version.workspace = true
 
 [lib]
 proc-macro = true
diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml
index 57747bc9341..ca1b04269fd 100644
--- a/rust/qemu-api/Cargo.toml
+++ b/rust/qemu-api/Cargo.toml
@@ -1,18 +1,17 @@
 [package]
 name = "qemu_api"
 version = "0.1.0"
-edition = "2021"
 authors = ["Manos Pitsidianakis <manos.pitsidianakis@linaro.org>"]
-license = "GPL-2.0-or-later"
-readme = "README.md"
-homepage = "https://www.qemu.org"
 description = "Rust bindings for QEMU"
-repository = "https://gitlab.com/qemu-project/qemu/"
+readme = "README.md"
 resolver = "2"
 publish = false
-keywords = []
-categories = []
-rust-version = "1.63.0"
+
+edition.workspace = true
+homepage.workspace = true
+license.workspace = true
+repository.workspace = true
+rust-version.workspace = true
 
 [dependencies]
 qemu_api_macros = { path = "../qemu-api-macros" }
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 13/13] monitor: don't wake up qmp_dispatcher_co coroutine upon cleanup
  2025-05-03  7:58 [PULL 00/13] Rust, i386 changes for 2025-05-03 Paolo Bonzini
                   ` (11 preceding siblings ...)
  2025-05-03  7:58 ` [PULL 12/13] rust: centralize config in workspace root Paolo Bonzini
@ 2025-05-03  7:58 ` Paolo Bonzini
  2025-05-06 13:58 ` [PULL 00/13] Rust, i386 changes for 2025-05-03 Stefan Hajnoczi
  13 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2025-05-03  7:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andrey Drobyshev

From: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>

Since the commit 3e6bed61 ("monitor: cleanup detection of qmp_dispatcher_co
shutting down"), coroutine pointer qmp_dispatcher_co is set to NULL upon
cleanup.  If a QMP command is sent after monitor_cleanup() (e.g. after
shutdown), this may lead to SEGFAULT on aio_co_wake(NULL).

As mentioned in the comment inside monitor_cleanup(), the intention is to
allow incoming requests while shutting down, but simply leave them
without any response.  Let's do exactly that, and if qmp_dispatcher_co
coroutine pointer has already been set to NULL, let's simply skip the
aio_co_wake() part.

Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
Link: https://lore.kernel.org/r/20250502214729.928380-2-andrey.drobyshev@virtuozzo.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 monitor/qmp.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/monitor/qmp.c b/monitor/qmp.c
index 2f46cf9e494..cb99a12d941 100644
--- a/monitor/qmp.c
+++ b/monitor/qmp.c
@@ -356,7 +356,8 @@ void qmp_dispatcher_co_wake(void)
     /* Write request before reading qmp_dispatcher_co_busy.  */
     smp_mb__before_rmw();
 
-    if (!qatomic_xchg(&qmp_dispatcher_co_busy, true)) {
+    if (!qatomic_xchg(&qmp_dispatcher_co_busy, true) &&
+            qatomic_read(&qmp_dispatcher_co)) {
         aio_co_wake(qmp_dispatcher_co);
     }
 }
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PULL 00/13] Rust, i386 changes for 2025-05-03
  2025-05-03  7:58 [PULL 00/13] Rust, i386 changes for 2025-05-03 Paolo Bonzini
                   ` (12 preceding siblings ...)
  2025-05-03  7:58 ` [PULL 13/13] monitor: don't wake up qmp_dispatcher_co coroutine upon cleanup Paolo Bonzini
@ 2025-05-06 13:58 ` Stefan Hajnoczi
  13 siblings, 0 replies; 16+ messages in thread
From: Stefan Hajnoczi @ 2025-05-06 13:58 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 116 bytes --]

Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/10.0 for any user-visible changes.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 484 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PULL 09/13] target/i386: do not trigger IRQ shadow for LSS
  2025-05-03  7:58 ` [PULL 09/13] target/i386: do not trigger IRQ shadow for LSS Paolo Bonzini
@ 2025-05-06 19:58   ` Michael Tokarev
  0 siblings, 0 replies; 16+ messages in thread
From: Michael Tokarev @ 2025-05-06 19:58 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel; +Cc: qemu-stable

On 03.05.2025 10:58, Paolo Bonzini wrote:
> Because LSS need not trigger an IRQ shadow, gen_movl_seg can't just use
> the destination register to decide whether to inhibit IRQs.  Add an
> argument.
> 
> Cc: qemu-stable@nongnu.org

This one does not apply cleanly (to 10.0) after 9a688e70bdb2f23112
"target/i386: tcg: remove some more uses of temporaries".

Can you take a look please, for back-porting this one to older
release(s), and for defining which releases (7.2, 9.2, 10.0)
need this change?

Thanks,

/mjt


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2025-05-06 20:06 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-03  7:58 [PULL 00/13] Rust, i386 changes for 2025-05-03 Paolo Bonzini
2025-05-03  7:58 ` [PULL 01/13] rust/vmstate: Add support for field_exists checks Paolo Bonzini
2025-05-03  7:58 ` [PULL 02/13] vmstate: support varray for vmstate_clock! Paolo Bonzini
2025-05-03  7:58 ` [PULL 03/13] rust: assertions: Support index field wrapped in BqlCell Paolo Bonzini
2025-05-03  7:58 ` [PULL 04/13] rust/vmstate_test: Test varray with num " Paolo Bonzini
2025-05-03  7:58 ` [PULL 05/13] rust/timer: Define NANOSECONDS_PER_SECOND binding as u64 Paolo Bonzini
2025-05-03  7:58 ` [PULL 06/13] rust/hpet: Support migration Paolo Bonzini
2025-05-03  7:58 ` [PULL 07/13] target/i386/emulate: remove rflags leftovers Paolo Bonzini
2025-05-03  7:58 ` [PULL 08/13] target/i386/hvf: fix a compilation error Paolo Bonzini
2025-05-03  7:58 ` [PULL 09/13] target/i386: do not trigger IRQ shadow for LSS Paolo Bonzini
2025-05-06 19:58   ` Michael Tokarev
2025-05-03  7:58 ` [PULL 10/13] target/i386: do not block singlestep for STI Paolo Bonzini
2025-05-03  7:58 ` [PULL 11/13] hw/char/serial: Remove unused prog_if compat property Paolo Bonzini
2025-05-03  7:58 ` [PULL 12/13] rust: centralize config in workspace root Paolo Bonzini
2025-05-03  7:58 ` [PULL 13/13] monitor: don't wake up qmp_dispatcher_co coroutine upon cleanup Paolo Bonzini
2025-05-06 13:58 ` [PULL 00/13] Rust, i386 changes for 2025-05-03 Stefan Hajnoczi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).