Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging

* rust: fix nightly warnings
* target/i386: a smattering of fixes
* monitor: add "info accelerators"
* kvm: cleanups to kvm_cpu_synchronize_put()
* target/i386: Add TSA attack variants and verw-clear feature flag
* async: tsan bottom half fixes
* rust: migration state wrappers with support for BQL-free devices

# -----BEGIN PGP SIGNATURE-----
#
# iQFIBAABCgAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmjuRZYUHHBib256aW5p
# QHJlZGhhdC5jb20ACgkQv/vSX3jHroPTFgf+LRXCvGJwrlJwD4cAS/TBzhzpOAMZ
# v75RZ/s2tF7nYRhT28MDtZWsXeVrjO/nrSXaThxe6WHfmKK2W+16a+BgfhbeTEGt
# wBnK3JMb84i7T2Foy91jVCc4k0igwZu6Wmnf3rOP9gpdjAK6FYLje1KWvF7FrJO1
# ackAzJJ+TiZmc5QpXLW8sjaIidmefveXsdHwMVRz67LDvlDANEhp4rixjTVmKe0Z
# UL3tzrEj/b15vvElkh3a1IrVAttexay425J94R5i3Xpz3fEBqmIdpJt4eiCt9j0L
# zL7TOXwSJWiOX+mec6aJwYh8y4ikD6Yq4f4Hc9xFBEZRcICaxx4uoOscYA==
# =FroL
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 14 Oct 2025 05:44:06 AM PDT
# gpg:                using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg:                issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [unknown]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [unknown]
# gpg: WARNING: The key's User ID is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* tag 'for-upstream' of https://gitlab.com/bonzini/qemu: (28 commits)
  rust: migration: implement ToMigrationState as part of impl_vmstate_bitsized
  timer: constify some functions
  rust: qemu-macros: add ToMigrationState derive macro
  rust: migration: add high-level migration wrappers
  rust: move VMState from bql to migration
  rust: migration: extract vmstate_fields_ref
  rust: migration: validate termination of subsection arrays
  rust: migration: do not store raw pointers into VMStateSubsectionsWrapper
  rust: migration: do not pass raw pointer to VMStateDescription::fields
  rust: bql: add BqlRefCell::get_mut()
  accel/kvm: Factor kvm_cpu_synchronize_put() out
  accel/kvm: Introduce KvmPutState enum
  monitor: generalize query-mshv/"info mshv" to query-accelerators/"info accelerators"
  monitor: clarify "info accel" help message
  target/i386: user: do not set up a valid LDT on reset
  async: access bottom half flags with qatomic_read
  target/i386: fix access to the T bit of the TSS
  target/i386: fix x86_64 pushw op
  i386/tcg/smm_helper: Properly apply DR values on SMM entry / exit
  i386/cpu: Prevent delivering SIPI during SMM in TCG mode
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson
2025-10-14 07:30:09 -07:00
42 changed files with 1230 additions and 149 deletions
+19 -28
View File
@@ -2937,22 +2937,32 @@ void kvm_cpu_synchronize_state(CPUState *cpu)
}
}
static void do_kvm_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg)
static bool kvm_cpu_synchronize_put(CPUState *cpu, KvmPutState state,
const char *desc)
{
Error *err = NULL;
int ret = kvm_arch_put_registers(cpu, KVM_PUT_RESET_STATE, &err);
int ret = kvm_arch_put_registers(cpu, state, &err);
if (ret) {
if (err) {
error_reportf_err(err, "Restoring resisters after reset: ");
error_reportf_err(err, "Restoring resisters %s: ", desc);
} else {
error_report("Failed to put registers after reset: %s",
error_report("Failed to put registers %s: %s", desc,
strerror(-ret));
}
cpu_dump_state(cpu, stderr, CPU_DUMP_CODE);
vm_stop(RUN_STATE_INTERNAL_ERROR);
return false;
}
cpu->vcpu_dirty = false;
return true;
}
static void do_kvm_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg)
{
if (!kvm_cpu_synchronize_put(cpu, KVM_PUT_RESET_STATE, "after reset")) {
cpu_dump_state(cpu, stderr, CPU_DUMP_CODE);
vm_stop(RUN_STATE_INTERNAL_ERROR);
}
}
void kvm_cpu_synchronize_post_reset(CPUState *cpu)
@@ -2966,19 +2976,9 @@ void kvm_cpu_synchronize_post_reset(CPUState *cpu)
static void do_kvm_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg)
{
Error *err = NULL;
int ret = kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE, &err);
if (ret) {
if (err) {
error_reportf_err(err, "Putting registers after init: ");
} else {
error_report("Failed to put registers after init: %s",
strerror(-ret));
}
if (!kvm_cpu_synchronize_put(cpu, KVM_PUT_FULL_STATE, "after init")) {
exit(1);
}
cpu->vcpu_dirty = false;
}
void kvm_cpu_synchronize_post_init(CPUState *cpu)
@@ -3168,20 +3168,11 @@ int kvm_cpu_exec(CPUState *cpu)
MemTxAttrs attrs;
if (cpu->vcpu_dirty) {
Error *err = NULL;
ret = kvm_arch_put_registers(cpu, KVM_PUT_RUNTIME_STATE, &err);
if (ret) {
if (err) {
error_reportf_err(err, "Putting registers after init: ");
} else {
error_report("Failed to put registers after init: %s",
strerror(-ret));
}
if (!kvm_cpu_synchronize_put(cpu, KVM_PUT_RUNTIME_STATE,
"at runtime")) {
ret = -1;
break;
}
cpu->vcpu_dirty = false;
}
kvm_arch_pre_run(cpu, run);
+1
View File
@@ -155,6 +155,7 @@ module status
``hwcore::irq`` complete
``hwcore::qdev`` stable
``hwcore::sysbus`` stable
``migration::migratable`` proof of concept
``migration::vmstate`` stable
``qom`` stable
``system::memory`` stable
+12 -7
View File
@@ -271,12 +271,12 @@ ERST
.name = "accel",
.args_type = "",
.params = "",
.help = "show accelerator info",
.help = "show accelerator statistics",
},
SRST
``info accel``
Show accelerator info.
Show accelerator statistics.
ERST
SRST
@@ -308,16 +308,21 @@ SRST
ERST
{
.name = "mshv",
.name = "accelerators",
.args_type = "",
.params = "",
.help = "show MSHV information",
.cmd = hmp_info_mshv,
.help = "show present and enabled information",
.cmd = hmp_info_accelerators,
},
SRST
``info mshv``
Show MSHV information.
``info accelerators``
Show which accelerators are compiled into a QEMU binary, and what accelerator
is in use. For example::
kvm qtest [tcg]
indicates that TCG in use, and that KVM and qtest are also available.
ERST
{
+12 -9
View File
@@ -163,19 +163,22 @@ void hmp_info_kvm(Monitor *mon, const QDict *qdict)
qapi_free_KvmInfo(info);
}
void hmp_info_mshv(Monitor *mon, const QDict *qdict)
void hmp_info_accelerators(Monitor *mon, const QDict *qdict)
{
MshvInfo *info;
AcceleratorInfo *info;
AcceleratorList *accel;
info = qmp_query_mshv(NULL);
monitor_printf(mon, "mshv support: ");
if (info->present) {
monitor_printf(mon, "%s\n", info->enabled ? "enabled" : "disabled");
} else {
monitor_printf(mon, "not compiled\n");
info = qmp_query_accelerators(NULL);
for (accel = info->present; accel; accel = accel->next) {
char trail = accel->next ? ' ' : '\n';
if (info->enabled == accel->value) {
monitor_printf(mon, "[%s]%c", Accelerator_str(accel->value), trail);
} else {
monitor_printf(mon, "%s%c", Accelerator_str(accel->value), trail);
}
}
qapi_free_MshvInfo(info);
qapi_free_AcceleratorInfo(info);
}
void hmp_info_uuid(Monitor *mon, const QDict *qdict)
+15 -5
View File
@@ -31,15 +31,25 @@
#include <sys/stat.h>
/*
* QMP query for MSHV
* QMP query for enabled and present accelerators
*/
MshvInfo *qmp_query_mshv(Error **errp)
AcceleratorInfo *qmp_query_accelerators(Error **errp)
{
MshvInfo *info = g_malloc0(sizeof(*info));
AcceleratorInfo *info = g_malloc0(sizeof(*info));
AccelClass *current_class = ACCEL_GET_CLASS(current_accel());
int i;
info->enabled = mshv_enabled();
info->present = accel_find("mshv");
for (i = ACCELERATOR__MAX; i-- > 0; ) {
const char *s = Accelerator_str(i);
AccelClass *this_class = accel_find(s);
if (this_class) {
QAPI_LIST_PREPEND(info->present, i);
if (this_class == current_class) {
info->enabled = i;
}
}
}
return info;
}
-2
View File
@@ -646,8 +646,6 @@ void apic_sipi(DeviceState *dev)
{
APICCommonState *s = APIC(dev);
cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI);
if (!s->wait_for_sipi)
return;
cpu_x86_load_seg_cache_sipi(s->cpu, s->sipi_vector);
+1 -1
View File
@@ -24,7 +24,7 @@ strList *hmp_split_at_comma(const char *str);
void hmp_info_name(Monitor *mon, const QDict *qdict);
void hmp_info_version(Monitor *mon, const QDict *qdict);
void hmp_info_kvm(Monitor *mon, const QDict *qdict);
void hmp_info_mshv(Monitor *mon, const QDict *qdict);
void hmp_info_accelerators(Monitor *mon, const QDict *qdict);
void hmp_info_status(Monitor *mon, const QDict *qdict);
void hmp_info_uuid(Monitor *mon, const QDict *qdict);
void hmp_info_chardev(Monitor *mon, const QDict *qdict);
+3 -3
View File
@@ -699,7 +699,7 @@ void timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time);
*
* Returns: true if the timer is pending
*/
bool timer_pending(QEMUTimer *ts);
bool timer_pending(const QEMUTimer *ts);
/**
* timer_expired:
@@ -710,7 +710,7 @@ bool timer_pending(QEMUTimer *ts);
*
* Returns: true if the timer has expired
*/
bool timer_expired(QEMUTimer *timer_head, int64_t current_time);
bool timer_expired(const QEMUTimer *timer_head, int64_t current_time);
/**
* timer_expire_time_ns:
@@ -720,7 +720,7 @@ bool timer_expired(QEMUTimer *timer_head, int64_t current_time);
*
* Returns: the expiry time in nanoseconds
*/
uint64_t timer_expire_time_ns(QEMUTimer *ts);
uint64_t timer_expire_time_ns(const QEMUTimer *ts);
/**
* timer_get:
+9 -7
View File
@@ -340,14 +340,16 @@ int kvm_arch_process_async_events(CPUState *cpu);
int kvm_arch_get_registers(CPUState *cpu, Error **errp);
/* state subset only touched by the VCPU itself during runtime */
#define KVM_PUT_RUNTIME_STATE 1
/* state subset modified during VCPU reset */
#define KVM_PUT_RESET_STATE 2
/* full state set, modified during initialization or on vmload */
#define KVM_PUT_FULL_STATE 3
typedef enum kvm_put_state {
/* state subset only touched by the VCPU itself during runtime */
KVM_PUT_RUNTIME_STATE = 1,
/* state subset modified during VCPU reset */
KVM_PUT_RESET_STATE = 2,
/* full state set, modified during initialization or on vmload */
KVM_PUT_FULL_STATE = 3,
} KvmPutState;
int kvm_arch_put_registers(CPUState *cpu, int level, Error **errp);
int kvm_arch_put_registers(CPUState *cpu, KvmPutState level, Error **errp);
int kvm_arch_get_default_type(MachineState *ms);
+36 -11
View File
@@ -56,30 +56,55 @@
'features': [ 'unstable' ] }
##
# @MshvInfo:
# @Accelerator:
#
# Information about support for MSHV acceleration
#
# @enabled: true if MSHV acceleration is active
# @hvf: Apple Hypervisor.framework
#
# @present: true if MSHV acceleration is built into this executable
# @kvm: KVM
#
# @mshv: Hyper-V
#
# @nvmm: NetBSD NVMM
#
# @qtest: QTest (dummy accelerator)
#
# @tcg: TCG (dynamic translation)
#
# @whpx: Windows Hypervisor Platform
#
# @xen: Xen
#
# Since: 10.2.0
##
{ 'struct': 'MshvInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }
{ 'enum': 'Accelerator', 'data': ['hvf', 'kvm', 'mshv', 'nvmm', 'qtest', 'tcg', 'whpx', 'xen'] }
##
# @query-mshv:
# @AcceleratorInfo:
#
# Return information about MSHV acceleration
# Information about support for various accelerators
#
# Returns: @MshvInfo
# @enabled: the accelerator that is in use
#
# Since: 10.0.92
# @present: the list of accelerators that are built into this executable
#
# Since: 10.2.0
##
{ 'struct': 'AcceleratorInfo', 'data': {'enabled': 'Accelerator', 'present': ['Accelerator']} }
##
# @query-accelerators:
#
# Return information about accelerators
#
# Returns: @AcceleratorInfo
#
# Since: 10.2.0
#
# .. qmp-example::
#
# -> { "execute": "query-mshv" }
# <- { "return": { "enabled": true, "present": true } }
# -> { "execute": "query-accelerators" }
# <- { "return": { "enabled": "mshv", "present": ["kvm", "mshv", "qtest", "tcg"] } }
##
{ 'command': 'query-mshv', 'returns': 'MshvInfo' }
{ 'command': 'query-accelerators', 'returns': 'AcceleratorInfo' }
+2 -1
View File
@@ -59,7 +59,6 @@ name = "bql"
version = "0.1.0"
dependencies = [
"glib-sys",
"migration",
]
[[package]]
@@ -198,8 +197,10 @@ checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
name = "migration"
version = "0.1.0"
dependencies = [
"bql",
"common",
"glib-sys",
"qemu_macros",
"util",
]
-1
View File
@@ -13,7 +13,6 @@ repository.workspace = true
rust-version.workspace = true
[dependencies]
migration = { path = "../migration" }
glib-sys.workspace = true
[features]
-1
View File
@@ -37,7 +37,6 @@ _bql_rs = static_library(
override_options: ['rust_std=2021', 'build.rust_std=2021'],
rust_abi: 'rust',
rust_args: _bql_cfg,
link_with: [_migration_rs],
dependencies: [glib_sys_rs],
)
+17 -6
View File
@@ -151,8 +151,6 @@ use std::{
ptr::NonNull,
};
use migration::impl_vmstate_transparent;
/// A mutable memory location that is protected by the Big QEMU Lock.
///
/// # Memory layout
@@ -364,8 +362,6 @@ impl<T: Default> BqlCell<T> {
}
}
impl_vmstate_transparent!(crate::cell::BqlCell<T> where T: VMState);
/// A mutable memory location with dynamically checked borrow rules,
/// protected by the Big QEMU Lock.
///
@@ -580,6 +576,23 @@ impl<T> BqlRefCell<T> {
}
}
/// Returns a mutable reference to the underlying data in this cell,
/// while the owner already has a mutable reference to the cell.
///
/// # Examples
///
/// ```
/// use bql::BqlRefCell;
///
/// let mut c = BqlRefCell::new(5);
///
/// *c.get_mut() = 10;
/// ```
#[inline]
pub const fn get_mut(&mut self) -> &mut T {
self.value.get_mut()
}
/// Returns a raw pointer to the underlying data in this cell.
///
/// # Examples
@@ -674,8 +687,6 @@ impl<T> From<T> for BqlRefCell<T> {
}
}
impl_vmstate_transparent!(crate::cell::BqlRefCell<T> where T: VMState);
struct BorrowRef<'b> {
borrow: &'b Cell<BorrowFlag>,
}
+1
View File
@@ -255,6 +255,7 @@ pub enum Mode {
#[bitsize(2)]
#[derive(Clone, Copy, Debug, Eq, FromBits, PartialEq)]
#[allow(clippy::enum_variant_names)]
/// `WLEN` Word length, field of [Line Control register](LineControl).
///
/// These bits indicate the number of data bits transmitted or received in a
+2 -2
View File
@@ -40,7 +40,7 @@ impl HPETFwConfig {
assert!(bql::is_locked());
// SAFETY: all accesses go through these methods, which guarantee
// that the accesses are protected by the BQL.
let mut fw_cfg = unsafe { *addr_of_mut!(hpet_fw_cfg) };
let fw_cfg = unsafe { &mut *addr_of_mut!(hpet_fw_cfg) };
if fw_cfg.count == u8::MAX {
// first instance
@@ -60,7 +60,7 @@ impl HPETFwConfig {
assert!(bql::is_locked());
// SAFETY: all accesses go through these methods, which guarantee
// that the accesses are protected by the BQL.
let mut fw_cfg = unsafe { *addr_of_mut!(hpet_fw_cfg) };
let fw_cfg = unsafe { &mut *addr_of_mut!(hpet_fw_cfg) };
fw_cfg.hpet[hpet_id].event_timer_block_id = timer_block_id;
fw_cfg.hpet[hpet_id].address = address;
+1 -1
View File
@@ -29,8 +29,8 @@ subdir('qemu-macros')
subdir('common')
subdir('bits')
subdir('util')
subdir('migration')
subdir('bql')
subdir('migration')
subdir('qom')
subdir('system')
subdir('chardev')
+2
View File
@@ -13,7 +13,9 @@ repository.workspace = true
rust-version.workspace = true
[dependencies]
bql = { path = "../bql" }
common = { path = "../common" }
qemu_macros = { path = "../qemu-macros" }
util = { path = "../util" }
glib-sys.workspace = true
+4 -3
View File
@@ -31,18 +31,19 @@ _migration_rs = static_library(
[
'src/lib.rs',
'src/bindings.rs',
'src/migratable.rs',
'src/vmstate.rs',
],
{'.' : _migration_bindings_inc_rs},
),
override_options: ['rust_std=2021', 'build.rust_std=2021'],
rust_abi: 'rust',
link_with: [_util_rs],
dependencies: [common_rs, glib_sys_rs],
link_with: [_util_rs, _bql_rs],
dependencies: [common_rs, glib_sys_rs, qemu_macros],
)
migration_rs = declare_dependency(link_with: [_migration_rs],
dependencies: [migration, qemuutil])
dependencies: [bql_rs, migration, qemuutil])
# Doctests are essentially integration tests, so they need the same dependencies.
# Note that running them requires the object files for C code, so place them
+5
View File
@@ -2,5 +2,10 @@
pub mod bindings;
pub use qemu_macros::ToMigrationState;
pub mod migratable;
pub use migratable::*;
pub mod vmstate;
pub use vmstate::*;

Some files were not shown because too many files have changed in this diff Show More