mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
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:
@@ -61,3 +61,6 @@ config HV_BALLOON_POSSIBLE
|
||||
|
||||
config HAVE_RUST
|
||||
bool
|
||||
|
||||
config MAC_PVG
|
||||
bool
|
||||
|
||||
+13
-6
@@ -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
|
||||
|
||||
@@ -332,6 +332,8 @@ bool machine_parse_smp_cache(MachineState *ms,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mc->smp_props.has_caches = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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
@@ -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'
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
Generated
+7
@@ -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",
|
||||
]
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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,2 +1,3 @@
|
||||
config X_HPET_RUST
|
||||
bool
|
||||
default y if PC && HAVE_RUST
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user