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

* qom: Use command line syntax for default values in help
* i386: support cache topology with machine's configuration
* rust: fix duplicate symbols from monitor-fd.c
* rust: add module to convert between success/-errno and io::Result
* rust: move class_init implementation from trait to method
* pvg: configuration improvements
* kvm guestmemfd: replace assertion with error
* riscv: cleanups
* target/i386/hvf: cleanups to emulation
* target/i386: add Zhaoxin and Yongfeng CPU model

# -----BEGIN PGP SIGNATURE-----
#
# iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAme+10sUHHBib256aW5p
# QHJlZGhhdC5jb20ACgkQv/vSX3jHroMkRwf/eT0gVbE3u0TS6EVZwjGZPHEOEyy/
# gl39SlTT97HxoAClE4PRcdkn7YR3f30hytHghc4qhou+Eh/7Mj2Ox7l7+CyaaCS/
# fxowsOVMBV7++PkyKRPxIMamKzD8Bo0eGwWe+CJijA0zt9PSI/YEwRV0pf/s6KCW
# pOya2f+aNbAo3O5RWtIKSISgbSVvuVzDcDHyfydmOHuvGr2NHAM8UfZYD+41qy5B
# 81PYlvK6HgvhaCboqCUADULkte96Xmc4p2ggk0ZNiy0ho46rs78SMyBh5sXR2S3I
# moiQHpJXyV5TcI7HmwvcW7s0/cpdKm/wmPOjb6otu9InWh/ON1nnURsTEQ==
# =V/fm
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 26 Feb 2025 16:56:43 HKT
# gpg:                using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg:                issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* tag 'for-upstream' of https://gitlab.com/bonzini/qemu: (34 commits)
  target/i386: Mask CMPLegacy bit in CPUID[0x80000001].ECX for Zhaoxin CPUs
  target/i386: Introduce Zhaoxin Yongfeng CPU model
  target/i386: Add CPUID leaf 0xC000_0001 EDX definitions
  target/i386: Add support for Zhaoxin CPU vendor identification
  target/riscv: move 128-bit check to TCG realize
  target/riscv: remove unused macro DEFINE_CPU
  i386/cpu: add has_caches flag to check smp_cache configuration
  i386/pc: Support cache topology in -machine for PC machine
  i386/cpu: Update cache topology with machine's configuration
  i386/cpu: Support module level cache topology
  rust: qom: get rid of ClassInitImpl
  rust: pl011, qemu_api tests: do not use ClassInitImpl
  rust: qom: add ObjectImpl::CLASS_INIT
  rust: add SysBusDeviceImpl
  rust: add IsA bounds to QOM implementation traits
  target/i386/hvf: drop some dead code
  target/i386/hvf: move and rename simulate_{rdmsr, wrmsr}
  target/i386/hvf: move and rename {load, store}_regs
  target/i386/hvf: use x86_segment in x86_decode.c
  target/i386/hvf: fix the declaration of hvf_handle_io
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi
2025-03-03 10:20:59 +08:00
53 changed files with 1275 additions and 579 deletions
+3
View File
@@ -61,3 +61,6 @@ config HV_BALLOON_POSSIBLE
config HAVE_RUST
bool
config MAC_PVG
bool
+13 -6
View File
@@ -139,16 +139,22 @@ anymore.
Writing Rust code in QEMU
-------------------------
Right now QEMU includes three crates:
QEMU includes four crates:
* ``qemu_api`` for bindings to C code and useful functionality
* ``qemu_api_macros`` defines several procedural macros that are useful when
writing C code
* ``pl011`` (under ``rust/hw/char/pl011``) is the sample device that is being
used to further develop ``qemu_api`` and ``qemu_api_macros``. It is a functional
replacement for the ``hw/char/pl011.c`` file.
* ``pl011`` (under ``rust/hw/char/pl011``) and ``hpet`` (under ``rust/hw/timer/hpet``)
are sample devices that demonstrate ``qemu_api`` and ``qemu_api_macros``, and are
used to further develop them. These two crates are functional\ [#issues]_ replacements
for the ``hw/char/pl011.c`` and ``hw/timer/hpet.c`` files.
.. [#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.
This section explains how to work with them.
@@ -179,6 +185,7 @@ module status
``callbacks`` complete
``cell`` stable
``c_str`` complete
``errno`` complete
``irq`` complete
``memory`` stable
``module`` complete
@@ -293,7 +300,7 @@ to a Rust mutable reference, and use a shared reference instead. Rust code
will then have to use QEMU's ``BqlRefCell`` and ``BqlCell`` type, which
enforce that locking rules for the "Big QEMU Lock" are respected. These cell
types are also known to the ``vmstate`` crate, which is able to "look inside"
them when building an in-memory representation of a ``struct``s layout.
them when building an in-memory representation of a ``struct``'s layout.
Note that the same is not true of a ``RefCell`` or ``Mutex``.
In the future, similar cell types might also be provided for ``AioContext``-based
@@ -349,7 +356,7 @@ Writing procedural macros
'''''''''''''''''''''''''
By conventions, procedural macros are split in two functions, one
returning ``Result<proc_macro2::TokenStream, MacroError>` with the body of
returning ``Result<proc_macro2::TokenStream, MacroError>`` with the body of
the procedural macro, and the second returning ``proc_macro::TokenStream``
which is the actual procedural macro. The former's name is the same as
the latter with the ``_or_error`` suffix. The code for the latter is more
+2
View File
@@ -332,6 +332,8 @@ bool machine_parse_smp_cache(MachineState *ms,
return false;
}
}
mc->smp_props.has_caches = true;
return true;
}
-4
View File
@@ -141,10 +141,6 @@ config XLNX_DISPLAYPORT
config DM163
bool
config MAC_PVG
bool
default y
config MAC_PVG_MMIO
bool
depends on MAC_PVG && AARCH64
+2 -7
View File
@@ -61,13 +61,8 @@ system_ss.add(when: 'CONFIG_ARTIST', if_true: files('artist.c'))
system_ss.add(when: 'CONFIG_ATI_VGA', if_true: [files('ati.c', 'ati_2d.c', 'ati_dbg.c'), pixman])
if host_os == 'darwin'
system_ss.add(when: 'CONFIG_MAC_PVG', if_true: [files('apple-gfx.m'), pvg, metal])
system_ss.add(when: 'CONFIG_MAC_PVG_PCI', if_true: [files('apple-gfx-pci.m'), pvg, metal])
if cpu == 'aarch64'
system_ss.add(when: 'CONFIG_MAC_PVG_MMIO', if_true: [files('apple-gfx-mmio.m'), pvg, metal])
endif
endif
system_ss.add(when: [pvg, 'CONFIG_MAC_PVG_PCI'], if_true: [files('apple-gfx.m', 'apple-gfx-pci.m')])
system_ss.add(when: [pvg, 'CONFIG_MAC_PVG_MMIO'], if_true: [files('apple-gfx.m', 'apple-gfx-mmio.m')])
if config_all_devices.has_key('CONFIG_VIRTIO_GPU')
virtio_gpu_ss = ss.source_set()
+4
View File
@@ -1798,6 +1798,10 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
mc->nvdimm_supported = true;
mc->smp_props.dies_supported = true;
mc->smp_props.modules_supported = true;
mc->smp_props.cache_supported[CACHE_LEVEL_AND_TYPE_L1D] = true;
mc->smp_props.cache_supported[CACHE_LEVEL_AND_TYPE_L1I] = true;
mc->smp_props.cache_supported[CACHE_LEVEL_AND_TYPE_L2] = true;
mc->smp_props.cache_supported[CACHE_LEVEL_AND_TYPE_L3] = true;
mc->default_ram_id = "pc.ram";
pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_AUTO;
+10 -28
View File
@@ -77,6 +77,7 @@ struct HPETState {
uint8_t rtc_irq_level;
qemu_irq pit_enabled;
uint8_t num_timers;
uint8_t num_timers_save;
uint32_t intcap;
HPETTimer timer[HPET_MAX_TIMERS];
@@ -237,15 +238,12 @@ static int hpet_pre_save(void *opaque)
s->hpet_counter = hpet_get_ticks(s);
}
return 0;
}
static int hpet_pre_load(void *opaque)
{
HPETState *s = opaque;
/* version 1 only supports 3, later versions will load the actual value */
s->num_timers = HPET_MIN_TIMERS;
/*
* 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.
*/
s->num_timers_save = s->num_timers;
return 0;
}
@@ -253,12 +251,7 @@ static bool hpet_validate_num_timers(void *opaque, int version_id)
{
HPETState *s = opaque;
if (s->num_timers < HPET_MIN_TIMERS) {
return false;
} else if (s->num_timers > HPET_MAX_TIMERS) {
return false;
}
return true;
return s->num_timers == s->num_timers_save;
}
static int hpet_post_load(void *opaque, int version_id)
@@ -277,16 +270,6 @@ static int hpet_post_load(void *opaque, int version_id)
- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
/* Push number of timers into capability returned via HPET_ID */
s->capability &= ~HPET_ID_NUM_TIM_MASK;
s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
hpet_fw_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability;
/* Derive HPET_MSI_SUPPORT from the capability of the first timer. */
s->flags &= ~(1 << HPET_MSI_SUPPORT);
if (s->timer[0].config & HPET_TN_FSB_CAP) {
s->flags |= 1 << HPET_MSI_SUPPORT;
}
return 0;
}
@@ -347,14 +330,13 @@ static const VMStateDescription vmstate_hpet = {
.version_id = 2,
.minimum_version_id = 1,
.pre_save = hpet_pre_save,
.pre_load = hpet_pre_load,
.post_load = hpet_post_load,
.fields = (const VMStateField[]) {
VMSTATE_UINT64(config, HPETState),
VMSTATE_UINT64(isr, HPETState),
VMSTATE_UINT64(hpet_counter, HPETState),
VMSTATE_UINT8_V(num_timers, HPETState, 2),
VMSTATE_VALIDATE("num_timers in range", hpet_validate_num_timers),
VMSTATE_UINT8_V(num_timers_save, HPETState, 2),
VMSTATE_VALIDATE("num_timers must match", hpet_validate_num_timers),
VMSTATE_STRUCT_VARRAY_UINT8(timer, HPETState, num_timers, 0,
vmstate_hpet_timer, HPETTimer),
VMSTATE_END_OF_LIST()
+3
View File
@@ -156,6 +156,8 @@ typedef struct {
* @modules_supported - whether modules are supported by the machine
* @cache_supported - whether cache (l1d, l1i, l2 and l3) configuration are
* supported by the machine
* @has_caches - whether cache properties are explicitly specified in the
* user provided smp-cache configuration
*/
typedef struct {
bool prefer_sockets;
@@ -166,6 +168,7 @@ typedef struct {
bool drawers_supported;
bool modules_supported;
bool cache_supported[CACHE_LEVEL_AND_TYPE__MAX];
bool has_caches;
} SMPCompatProps;
/**
+11 -3
View File
@@ -821,7 +821,6 @@ version_res = []
coref = []
iokit = []
pvg = not_found
metal = []
emulator_link_args = []
midl = not_found
widl = not_found
@@ -843,8 +842,8 @@ elif host_os == 'darwin'
coref = dependency('appleframeworks', modules: 'CoreFoundation')
iokit = dependency('appleframeworks', modules: 'IOKit', required: false)
host_dsosuf = '.dylib'
pvg = dependency('appleframeworks', modules: 'ParavirtualizedGraphics')
metal = dependency('appleframeworks', modules: 'Metal')
pvg = dependency('appleframeworks', modules: ['ParavirtualizedGraphics', 'Metal'],
required: get_option('pvg'))
elif host_os == 'sunos'
socket = [cc.find_library('socket'),
cc.find_library('nsl'),
@@ -3367,6 +3366,12 @@ foreach target : target_dirs
target_kconfig += 'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'
target_kconfig += 'CONFIG_TARGET_BIG_ENDIAN=' + config_target['TARGET_BIG_ENDIAN']
# PVG is not cross-architecture. Use accelerator_targets as a proxy to
# figure out which target can support PVG on this host
if pvg.found() and target in accelerator_targets.get('CONFIG_HVF', [])
target_kconfig += 'CONFIG_MAC_PVG=y'
endif
config_input = meson.get_external_property(target, 'default')
config_devices_mak = target + '-config-devices.mak'
config_devices_mak = configure_file(
@@ -4840,6 +4845,9 @@ summary_info += {'libdw': libdw}
if host_os == 'freebsd'
summary_info += {'libinotify-kqueue': inotify}
endif
if host_os == 'darwin'
summary_info += {'ParavirtualizedGraphics support': pvg}
endif
summary(summary_info, bool_yn: true, section: 'Dependencies')
if host_arch == 'unknown'
+2
View File
@@ -198,6 +198,8 @@ option('lzfse', type : 'feature', value : 'auto',
description: 'lzfse support for DMG images')
option('lzo', type : 'feature', value : 'auto',
description: 'lzo compression support')
option('pvg', type: 'feature', value: 'auto',
description: 'macOS paravirtualized graphics support')
option('rbd', type : 'feature', value : 'auto',
description: 'Ceph block device driver')
option('opengl', type : 'feature', value : 'auto',
+29 -1
View File
@@ -42,7 +42,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
" aux-ram-share=on|off allocate auxiliary guest RAM as shared (default: off)\n"
#endif
" memory-backend='backend-id' specifies explicitly provided backend for main RAM (default=none)\n"
" cxl-fmw.0.targets.0=firsttarget,cxl-fmw.0.targets.1=secondtarget,cxl-fmw.0.size=size[,cxl-fmw.0.interleave-granularity=granularity]\n",
" cxl-fmw.0.targets.0=firsttarget,cxl-fmw.0.targets.1=secondtarget,cxl-fmw.0.size=size[,cxl-fmw.0.interleave-granularity=granularity]\n"
" smp-cache.0.cache=cachename,smp-cache.0.topology=topologylevel\n",
QEMU_ARCH_ALL)
SRST
``-machine [type=]name[,prop=value[,...]]``
@@ -172,6 +173,33 @@ SRST
::
-machine cxl-fmw.0.targets.0=cxl.0,cxl-fmw.0.targets.1=cxl.1,cxl-fmw.0.size=128G,cxl-fmw.0.interleave-granularity=512
``smp-cache.0.cache=cachename,smp-cache.0.topology=topologylevel``
Define cache properties for SMP system.
``cache=cachename`` specifies the cache that the properties will be
applied on. This field is the combination of cache level and cache
type. It supports ``l1d`` (L1 data cache), ``l1i`` (L1 instruction
cache), ``l2`` (L2 unified cache) and ``l3`` (L3 unified cache).
``topology=topologylevel`` sets the cache topology level. It accepts
CPU topology levels including ``core``, ``module``, ``cluster``, ``die``,
``socket``, ``book``, ``drawer`` and a special value ``default``. If
``default`` is set, then the cache topology will follow the architecture's
default cache topology model. If another topology level is set, the cache
will be shared at corresponding CPU topology level. For example,
``topology=core`` makes the cache shared by all threads within a core.
The omitting cache will default to using the ``default`` level.
The default cache topology model for an i386 PC machine is as follows:
``l1d``, ``l1i``, and ``l2`` caches are per ``core``, while the ``l3``
cache is per ``die``.
Example:
::
-machine smp-cache.0.cache=l1d,smp-cache.0.topology=core,smp-cache.1.cache=l1i,smp-cache.1.topology=core
ERST
DEF("M", HAS_ARG, QEMU_OPTION_M,
+21 -3
View File
@@ -4,9 +4,11 @@
#include "qapi/error.h"
#include "qapi/qapi-visit-qom.h"
#include "qobject/qobject.h"
#include "qobject/qbool.h"
#include "qobject/qdict.h"
#include "qapi/qmp/qerror.h"
#include "qobject/qjson.h"
#include "qobject/qstring.h"
#include "qapi/qobject-input-visitor.h"
#include "qapi/qobject-output-visitor.h"
#include "qom/object_interfaces.h"
@@ -177,9 +179,25 @@ char *object_property_help(const char *name, const char *type,
g_string_append(str, description);
}
if (defval) {
g_autofree char *def_json = g_string_free(qobject_to_json(defval),
false);
g_string_append_printf(str, " (default: %s)", def_json);
g_autofree char *def_json = NULL;
const char *def;
switch (qobject_type(defval)) {
case QTYPE_QSTRING:
def = qstring_get_str(qobject_to(QString, defval));
break;
case QTYPE_QBOOL:
def = qbool_get_bool(qobject_to(QBool, defval)) ? "on" : "off";
break;
default:
def_json = g_string_free(qobject_to_json(defval), false);
def = def_json;
break;
}
g_string_append_printf(str, " (default: %s)", def);
}
return g_string_free(str, false);
+7
View File
@@ -54,6 +54,12 @@ dependencies = [
"either",
]
[[package]]
name = "libc"
version = "0.2.162"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398"
[[package]]
name = "pl011"
version = "0.1.0"
@@ -100,6 +106,7 @@ dependencies = [
name = "qemu_api"
version = "0.1.0"
dependencies = [
"libc",
"qemu_api_macros",
"version_check",
]
+26 -20
View File
@@ -2,10 +2,10 @@
// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
// SPDX-License-Identifier: GPL-2.0-or-later
use core::ptr::{addr_of, addr_of_mut, NonNull};
use std::{
ffi::CStr,
os::raw::{c_int, c_void},
ptr::{addr_of, addr_of_mut, NonNull},
};
use qemu_api::{
@@ -19,8 +19,8 @@ use qemu_api::{
memory::{hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder},
prelude::*,
qdev::{Clock, ClockEvent, DeviceImpl, DeviceState, Property, ResetType, ResettablePhasesImpl},
qom::{ClassInitImpl, ObjectImpl, Owned, ParentField},
sysbus::{SysBusDevice, SysBusDeviceClass},
qom::{ObjectImpl, Owned, ParentField},
sysbus::{SysBusDevice, SysBusDeviceImpl},
vmstate::VMStateDescription,
};
@@ -50,11 +50,6 @@ impl std::ops::Index<hwaddr> for DeviceId {
}
}
impl DeviceId {
const ARM: Self = Self(&[0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1]);
const LUMINARY: Self = Self(&[0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1]);
}
// FIFOs use 32-bit indices instead of usize, for compatibility with
// the migration stream produced by the C version of this device.
#[repr(transparent)]
@@ -143,16 +138,24 @@ pub struct PL011Class {
device_id: DeviceId,
}
trait PL011Impl: SysBusDeviceImpl + IsA<PL011State> {
const DEVICE_ID: DeviceId;
}
impl PL011Class {
fn class_init<T: PL011Impl>(&mut self) {
self.device_id = T::DEVICE_ID;
self.parent_class.class_init::<T>();
}
}
unsafe impl ObjectType for PL011State {
type Class = PL011Class;
const TYPE_NAME: &'static CStr = crate::TYPE_PL011;
}
impl ClassInitImpl<PL011Class> for PL011State {
fn class_init(klass: &mut PL011Class) {
klass.device_id = DeviceId::ARM;
<Self as ClassInitImpl<SysBusDeviceClass>>::class_init(&mut klass.parent_class);
}
impl PL011Impl for PL011State {
const DEVICE_ID: DeviceId = DeviceId(&[0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1]);
}
impl ObjectImpl for PL011State {
@@ -160,6 +163,7 @@ impl ObjectImpl for PL011State {
const INSTANCE_INIT: Option<unsafe fn(&mut Self)> = Some(Self::init);
const INSTANCE_POST_INIT: Option<fn(&Self)> = Some(Self::post_init);
const CLASS_INIT: fn(&mut Self::Class) = Self::Class::class_init::<Self>;
}
impl DeviceImpl for PL011State {
@@ -176,6 +180,8 @@ impl ResettablePhasesImpl for PL011State {
const HOLD: Option<fn(&Self, ResetType)> = Some(Self::reset_hold);
}
impl SysBusDeviceImpl for PL011State {}
impl PL011Registers {
pub(self) fn read(&mut self, offset: RegisterOffset) -> (bool, u32) {
use RegisterOffset::*;
@@ -726,13 +732,6 @@ pub struct PL011Luminary {
parent_obj: ParentField<PL011State>,
}
impl ClassInitImpl<PL011Class> for PL011Luminary {
fn class_init(klass: &mut PL011Class) {
klass.device_id = DeviceId::LUMINARY;
<Self as ClassInitImpl<SysBusDeviceClass>>::class_init(&mut klass.parent_class);
}
}
qom_isa!(PL011Luminary : PL011State, SysBusDevice, DeviceState, Object);
unsafe impl ObjectType for PL011Luminary {
@@ -742,7 +741,14 @@ unsafe impl ObjectType for PL011Luminary {
impl ObjectImpl for PL011Luminary {
type ParentType = PL011State;
const CLASS_INIT: fn(&mut Self::Class) = Self::Class::class_init::<Self>;
}
impl PL011Impl for PL011Luminary {
const DEVICE_ID: DeviceId = DeviceId(&[0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1]);
}
impl DeviceImpl for PL011Luminary {}
impl ResettablePhasesImpl for PL011Luminary {}
impl SysBusDeviceImpl for PL011Luminary {}
+4 -2
View File
@@ -2,8 +2,10 @@
// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
// SPDX-License-Identifier: GPL-2.0-or-later
use core::ptr::NonNull;
use std::os::raw::{c_int, c_void};
use std::{
os::raw::{c_int, c_void},
ptr::NonNull,
};
use qemu_api::{
bindings::*, c_str, prelude::*, vmstate_clock, vmstate_fields, vmstate_of, vmstate_struct,
+1
View File
@@ -1,2 +1,3 @@
config X_HPET_RUST
bool
default y if PC && HAVE_RUST
+4 -1
View File
@@ -23,7 +23,7 @@ use qemu_api::{
qdev::{DeviceImpl, DeviceMethods, DeviceState, Property, ResetType, ResettablePhasesImpl},
qom::{ObjectImpl, ObjectType, ParentField},
qom_isa,
sysbus::SysBusDevice,
sysbus::{SysBusDevice, SysBusDeviceImpl},
timer::{Timer, CLOCK_VIRTUAL},
};
@@ -836,6 +836,7 @@ impl ObjectImpl for HPETState {
const INSTANCE_INIT: Option<unsafe fn(&mut Self)> = Some(Self::init);
const INSTANCE_POST_INIT: Option<fn(&Self)> = Some(Self::post_init);
const CLASS_INIT: fn(&mut Self::Class) = Self::Class::class_init::<Self>;
}
// TODO: Make these properties user-configurable!
@@ -887,3 +888,5 @@ impl DeviceImpl for HPETState {
impl ResettablePhasesImpl for HPETState {
const HOLD: Option<fn(&Self, ResetType)> = Some(Self::reset_hold);
}
impl SysBusDeviceImpl for HPETState {}
+1
View File
@@ -16,6 +16,7 @@ rust-version = "1.63.0"
[dependencies]
qemu_api_macros = { path = "../qemu-api-macros" }
libc = "0.2.162"
[build-dependencies]
version_check = "~0.9"
+4
View File
@@ -2,6 +2,8 @@ _qemu_api_cfg = run_command(rustc_args,
'--config-headers', config_host_h, '--features', files('Cargo.toml'),
capture: true, check: true).stdout().strip().splitlines()
libc_dep = dependency('libc-0.2-rs')
# _qemu_api_cfg += ['--cfg', 'feature="allocator"']
if rustc.version().version_compare('>=1.77.0')
_qemu_api_cfg += ['--cfg', 'has_offset_of']
@@ -22,6 +24,7 @@ _qemu_api_rs = static_library(
'src/cell.rs',
'src/chardev.rs',
'src/c_str.rs',
'src/errno.rs',
'src/irq.rs',
'src/memory.rs',
'src/module.rs',
@@ -39,6 +42,7 @@ _qemu_api_rs = static_library(
override_options: ['rust_std=2021', 'build.rust_std=2021'],
rust_abi: 'rust',
rust_args: _qemu_api_cfg,
dependencies: libc_dep,
)
rust.test('rust-qemu-api-tests', _qemu_api_rs,
+28
View File
@@ -92,3 +92,31 @@ macro_rules! assert_field_type {
};
};
}
/// Assert that an expression matches a pattern. This can also be
/// useful to compare enums that do not implement `Eq`.
///
/// # Examples
///
/// ```
/// # use qemu_api::assert_match;
/// // JoinHandle does not implement `Eq`, therefore the result
/// // does not either.
/// let result: Result<std::thread::JoinHandle<()>, u32> = Err(42);
/// assert_match!(result, Err(42));
/// ```
#[macro_export]
macro_rules! assert_match {
($a:expr, $b:pat) => {
assert!(
match $a {
$b => true,
_ => false,
},
"{} = {:?} does not match {}",
stringify!($a),
$a,
stringify!($b)
);
};
}

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