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

* target/i386: optimize string instructions
* target/i386: new Sierra Forest and Clearwater Forest models
* rust: type-safe vmstate implementation
* rust: use interior mutability for PL011
* rust: clean ups
* memtxattrs: remove usage of bitfields from MEMTXATTRS_UNSPECIFIED
* gitlab-ci: enable Rust backtraces

# -----BEGIN PGP SIGNATURE-----
#
# iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmeZ6VYUHHBib256aW5p
# QHJlZGhhdC5jb20ACgkQv/vSX3jHroMjbQgApuooMOp0z/8Ky4/ux8M8/vrlcNCH
# V1Pm6WzrjEzd9TIMLGr6npOyLOkWI31Aa4o/TuW09SeKE3dpCf/7LYA5VDEtkH79
# F57MgnSj56sMNgu+QZ/SiGvkKJXl+3091jIianrrI0dtX8hPonm6bt55woDvQt3z
# p94+4zzv5G0nc+ncITCDho8sn5itdZWVOjf9n6VCOumMjF4nRSoMkJKYIvjNht6n
# GtjMhYA70tzjkIi4bPyYkhFpMNlAqEDIp2TvPzp6klG5QoUErHIzdzoRTAtE4Dpb
# 7240r6jarQX41TBXGOFq0NrxES1cm5zO/6159D24qZGHGm2hG4nDx+t2jw==
# =ZKFy
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 29 Jan 2025 03:39:50 EST
# 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: (49 commits)
  gitlab-ci: include full Rust backtraces in test runs
  rust: qemu-api: add sub-subclass to the integration tests
  rust/zeroable: Implement Zeroable with const_zero macro
  rust: qdev: make reset take a shared reference
  rust: pl011: drop use of ControlFlow
  rust: pl011: pull device-specific code out of MemoryRegionOps callbacks
  rust: pl011: remove duplicate definitions
  rust: pl011: wrap registers with BqlRefCell
  rust: pl011: extract PL011Registers
  rust: pl011: pull interrupt updates out of read/write ops
  rust: pl011: extract CharBackend receive logic into a separate function
  rust: pl011: extract conversion to RegisterOffset
  rust: pl011: hide unnecessarily "pub" items from outside pl011::device
  rust: pl011: remove unnecessary "extern crate"
  rust: prefer NonNull::new to assertions
  rust: vmstate: make order of parameters consistent in vmstate_clock
  rust: vmstate: remove translation of C vmstate macros
  rust: pl011: switch vmstate to new-style macros
  rust: qemu_api: add vmstate_struct
  rust: vmstate: add public utility macros to implement VMState
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi
2025-01-29 09:51:03 -05:00
18 changed files with 1423 additions and 855 deletions
+1
View File
@@ -63,6 +63,7 @@
stage: test
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:$QEMU_CI_CONTAINER_TAG
script:
- export RUST_BACKTRACE=1
- source scripts/ci/gitlab-ci-section
- section_start buildenv "Setting up to run tests"
- scripts/git-submodule.sh update roms/SLOF
+46 -4
View File
@@ -71,6 +71,16 @@ mixture of host CPU models between machines, if live migration
compatibility is required, use the newest CPU model that is compatible
across all desired hosts.
``ClearwaterForest``
Intel Xeon Processor (ClearwaterForest, 2025)
``SierraForest``, ``SierraForest-v2``
Intel Xeon Processor (SierraForest, 2024), SierraForest-v2 mitigates
the GDS and RFDS vulnerabilities with stepping 3.
``GraniteRapids``, ``GraniteRapids-v2``
Intel Xeon Processor (GraniteRapids, 2024)
``Cascadelake-Server``, ``Cascadelake-Server-noTSX``
Intel Xeon Processor (Cascade Lake, 2019), with "stepping" levels 6
or 7 only. (The Cascade Lake Xeon processor with *stepping 5 is
@@ -181,7 +191,7 @@ features are included if using "Host passthrough" or "Host model".
CVE-2018-12127, [MSBDS] CVE-2018-12126).
This is an MSR (Model-Specific Register) feature rather than a CPUID feature,
so it will not appear in the Linux ``/proc/cpuinfo`` in the host or
therefore it will not appear in the Linux ``/proc/cpuinfo`` in the host or
guest. Instead, the host kernel uses it to populate the MDS
vulnerability file in ``sysfs``.
@@ -189,10 +199,10 @@ features are included if using "Host passthrough" or "Host model".
affected} in the ``/sys/devices/system/cpu/vulnerabilities/mds`` file.
``taa-no``
Recommended to inform that the guest that the host is ``not``
Recommended to inform the guest that the host is ``not``
vulnerable to CVE-2019-11135, TSX Asynchronous Abort (TAA).
This too is an MSR feature, so it does not show up in the Linux
This is also an MSR feature, therefore it does not show up in the Linux
``/proc/cpuinfo`` in the host or guest.
It should only be enabled for VMs if the host reports ``Not affected``
@@ -214,7 +224,7 @@ features are included if using "Host passthrough" or "Host model".
By disabling TSX, KVM-based guests can avoid paying the price of
mitigating TSX-based attacks.
Note that ``tsx-ctrl`` too is an MSR feature, so it does not show
Note that ``tsx-ctrl`` is also an MSR feature, therefore it does not show
up in the Linux ``/proc/cpuinfo`` in the host or guest.
To validate that Intel TSX is indeed disabled for the guest, there are
@@ -223,6 +233,38 @@ features are included if using "Host passthrough" or "Host model".
``/sys/devices/system/cpu/vulnerabilities/tsx_async_abort`` file in
the guest should report ``Mitigation: TSX disabled``.
``bhi-no``
Recommended to inform the guest that the host is ``not``
vulnerable to CVE-2022-0001, Branch History Injection (BHI).
This is also an MSR feature, therefore it does not show up in the Linux
``/proc/cpuinfo`` in the host or guest.
It should only be enabled for VMs if the host reports
``BHI: Not affected`` in the
``/sys/devices/system/cpu/vulnerabilities/spectre_v2`` file.
``gds-no``
Recommended to inform the guest that the host is ``not``
vulnerable to CVE-2022-40982, Gather Data Sampling (GDS).
This is also an MSR feature, therefore it does not show up in the Linux
``/proc/cpuinfo`` in the host or guest.
It should only be enabled for VMs if the host reports ``Not affected``
in the ``/sys/devices/system/cpu/vulnerabilities/gather_data_sampling``
file.
``rfds-no``
Recommended to inform the guest that the host is ``not``
vulnerable to CVE-2023-28746, Register File Data Sampling (RFDS).
This is also an MSR feature, therefore it does not show up in the Linux
``/proc/cpuinfo`` in the host or guest.
It should only be enabled for VMs if the host reports ``Not affected``
in the ``/sys/devices/system/cpu/vulnerabilities/reg_file_data_sampling``
file.
Preferred CPU models for AMD x86 hosts
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+14 -7
View File
@@ -23,12 +23,6 @@
* different semantics.
*/
typedef struct MemTxAttrs {
/* Bus masters which don't specify any attributes will get this
* (via the MEMTXATTRS_UNSPECIFIED constant), so that we can
* distinguish "all attributes deliberately clear" from
* "didn't specify" if necessary.
*/
unsigned int unspecified:1;
/*
* ARM/AMBA: TrustZone Secure access
* x86: System Management Mode access
@@ -57,14 +51,27 @@ typedef struct MemTxAttrs {
* PID (PCI PASID) support: Limited to 8 bits process identifier.
*/
unsigned int pid:8;
/*
* Bus masters which don't specify any attributes will get this
* (via the MEMTXATTRS_UNSPECIFIED constant), so that we can
* distinguish "all attributes deliberately clear" from
* "didn't specify" if necessary.
*/
bool unspecified;
uint8_t _reserved1;
uint16_t _reserved2;
} MemTxAttrs;
QEMU_BUILD_BUG_ON(sizeof(MemTxAttrs) > 8);
/* Bus masters which don't specify any attributes will get this,
* which has all attribute bits clear except the topmost one
* (so that we can distinguish "all attributes deliberately clear"
* from "didn't specify" if necessary).
*/
#define MEMTXATTRS_UNSPECIFIED ((MemTxAttrs) { .unspecified = 1 })
#define MEMTXATTRS_UNSPECIFIED ((MemTxAttrs) { .unspecified = true })
/* New-style MMIO accessors can indicate that the transaction failed.
* A zero (MEMTX_OK) response means success; anything else is a failure
File diff suppressed because it is too large Load Diff
+39 -34
View File
@@ -6,45 +6,64 @@ use core::ptr::NonNull;
use std::os::raw::{c_int, c_void};
use qemu_api::{
bindings::*, c_str, vmstate_clock, vmstate_fields, vmstate_subsections, vmstate_uint32,
vmstate_uint32_array, vmstate_unused, zeroable::Zeroable,
bindings::*, c_str, prelude::*, vmstate_clock, vmstate_fields, vmstate_of, vmstate_struct,
vmstate_subsections, vmstate_unused, zeroable::Zeroable,
};
use crate::device::{PL011State, PL011_FIFO_DEPTH};
use crate::device::{PL011Registers, PL011State};
#[allow(clippy::missing_const_for_fn)]
extern "C" fn pl011_clock_needed(opaque: *mut c_void) -> bool {
unsafe {
debug_assert!(!opaque.is_null());
let state = NonNull::new_unchecked(opaque.cast::<PL011State>());
state.as_ref().migrate_clock
}
let state = NonNull::new(opaque).unwrap().cast::<PL011State>();
unsafe { state.as_ref().migrate_clock }
}
/// Migration subsection for [`PL011State`] clock.
pub static VMSTATE_PL011_CLOCK: VMStateDescription = VMStateDescription {
static VMSTATE_PL011_CLOCK: VMStateDescription = VMStateDescription {
name: c_str!("pl011/clock").as_ptr(),
version_id: 1,
minimum_version_id: 1,
needed: Some(pl011_clock_needed),
fields: vmstate_fields! {
vmstate_clock!(clock, PL011State),
vmstate_clock!(PL011State, clock),
},
..Zeroable::ZERO
};
extern "C" fn pl011_post_load(opaque: *mut c_void, version_id: c_int) -> c_int {
unsafe {
debug_assert!(!opaque.is_null());
let mut state = NonNull::new_unchecked(opaque.cast::<PL011State>());
let result = state.as_mut().post_load(version_id as u32);
if result.is_err() {
-1
} else {
0
}
let state = NonNull::new(opaque).unwrap().cast::<PL011State>();
let result = unsafe { state.as_ref().post_load(version_id as u32) };
if result.is_err() {
-1
} else {
0
}
}
static VMSTATE_PL011_REGS: VMStateDescription = VMStateDescription {
name: c_str!("pl011/regs").as_ptr(),
version_id: 2,
minimum_version_id: 2,
fields: vmstate_fields! {
vmstate_of!(PL011Registers, flags),
vmstate_of!(PL011Registers, line_control),
vmstate_of!(PL011Registers, receive_status_error_clear),
vmstate_of!(PL011Registers, control),
vmstate_of!(PL011Registers, dmacr),
vmstate_of!(PL011Registers, int_enabled),
vmstate_of!(PL011Registers, int_level),
vmstate_of!(PL011Registers, read_fifo),
vmstate_of!(PL011Registers, ilpr),
vmstate_of!(PL011Registers, ibrd),
vmstate_of!(PL011Registers, fbrd),
vmstate_of!(PL011Registers, ifl),
vmstate_of!(PL011Registers, read_pos),
vmstate_of!(PL011Registers, read_count),
vmstate_of!(PL011Registers, read_trigger),
},
..Zeroable::ZERO
};
pub static VMSTATE_PL011: VMStateDescription = VMStateDescription {
name: c_str!("pl011").as_ptr(),
version_id: 2,
@@ -52,21 +71,7 @@ pub static VMSTATE_PL011: VMStateDescription = VMStateDescription {
post_load: Some(pl011_post_load),
fields: vmstate_fields! {
vmstate_unused!(core::mem::size_of::<u32>()),
vmstate_uint32!(flags, PL011State),
vmstate_uint32!(line_control, PL011State),
vmstate_uint32!(receive_status_error_clear, PL011State),
vmstate_uint32!(control, PL011State),
vmstate_uint32!(dmacr, PL011State),
vmstate_uint32!(int_enabled, PL011State),
vmstate_uint32!(int_level, PL011State),
vmstate_uint32_array!(read_fifo, PL011State, PL011_FIFO_DEPTH),
vmstate_uint32!(ilpr, PL011State),
vmstate_uint32!(ibrd, PL011State),
vmstate_uint32!(fbrd, PL011State),
vmstate_uint32!(ifl, PL011State),
vmstate_uint32!(read_pos, PL011State),
vmstate_uint32!(read_count, PL011State),
vmstate_uint32!(read_trigger, PL011State),
vmstate_struct!(PL011State, regs, &VMSTATE_PL011_REGS, BqlRefCell<PL011Registers>),
},
subsections: vmstate_subsections! {
VMSTATE_PL011_CLOCK
+29 -40
View File
@@ -25,15 +25,13 @@
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::result_unit_err)]
extern crate bilge;
extern crate bilge_impl;
extern crate qemu_api;
use qemu_api::c_str;
pub mod device;
pub mod device_class;
pub mod memory_ops;
mod device;
mod device_class;
mod memory_ops;
pub use device::pl011_create;
pub const TYPE_PL011: &::std::ffi::CStr = c_str!("pl011");
pub const TYPE_PL011_LUMINARY: &::std::ffi::CStr = c_str!("pl011_luminary");
@@ -45,8 +43,8 @@ pub const TYPE_PL011_LUMINARY: &::std::ffi::CStr = c_str!("pl011_luminary");
#[doc(alias = "offset")]
#[allow(non_camel_case_types)]
#[repr(u64)]
#[derive(Debug, qemu_api_macros::TryInto)]
pub enum RegisterOffset {
#[derive(Debug, Eq, PartialEq, qemu_api_macros::TryInto)]
enum RegisterOffset {
/// Data Register
///
/// A write to this register initiates the actual data transmission
@@ -102,10 +100,11 @@ pub enum RegisterOffset {
//Reserved = 0x04C,
}
pub mod registers {
mod registers {
//! Device registers exposed as typed structs which are backed by arbitrary
//! integer bitmaps. [`Data`], [`Control`], [`LineControl`], etc.
use bilge::prelude::*;
use qemu_api::impl_vmstate_bitsized;
/// Receive Status Register / Data Register common error bits
///
@@ -172,6 +171,7 @@ pub mod registers {
pub errors: Errors,
_reserved: u16,
}
impl_vmstate_bitsized!(Data);
impl Data {
// bilge is not very const-friendly, unfortunately
@@ -208,6 +208,7 @@ pub mod registers {
pub errors: Errors,
_reserved_unpredictable: u24,
}
impl_vmstate_bitsized!(ReceiveStatusErrorClear);
impl ReceiveStatusErrorClear {
pub fn set_from_data(&mut self, data: Data) {
@@ -280,6 +281,7 @@ pub mod registers {
pub ring_indicator: bool,
_reserved_zero_no_modify: u23,
}
impl_vmstate_bitsized!(Flags);
impl Flags {
pub fn reset(&mut self) {
@@ -354,6 +356,7 @@ pub mod registers {
/// 31:8 - Reserved, do not modify, read as zero.
_reserved_zero_no_modify: u24,
}
impl_vmstate_bitsized!(LineControl);
impl LineControl {
pub fn reset(&mut self) {
@@ -498,6 +501,7 @@ pub mod registers {
/// 31:16 - Reserved, do not modify, read as zero.
_reserved_zero_no_modify2: u16,
}
impl_vmstate_bitsized!(Control);
impl Control {
pub fn reset(&mut self) {
@@ -516,38 +520,23 @@ pub mod registers {
}
/// Interrupt status bits in UARTRIS, UARTMIS, UARTIMSC
pub const INT_OE: u32 = 1 << 10;
pub const INT_BE: u32 = 1 << 9;
pub const INT_PE: u32 = 1 << 8;
pub const INT_FE: u32 = 1 << 7;
pub const INT_RT: u32 = 1 << 6;
pub const INT_TX: u32 = 1 << 5;
pub const INT_RX: u32 = 1 << 4;
pub const INT_DSR: u32 = 1 << 3;
pub const INT_DCD: u32 = 1 << 2;
pub const INT_CTS: u32 = 1 << 1;
pub const INT_RI: u32 = 1 << 0;
pub const INT_E: u32 = INT_OE | INT_BE | INT_PE | INT_FE;
pub const INT_MS: u32 = INT_RI | INT_DSR | INT_DCD | INT_CTS;
#[repr(u32)]
pub enum Interrupt {
OE = 1 << 10,
BE = 1 << 9,
PE = 1 << 8,
FE = 1 << 7,
RT = 1 << 6,
TX = 1 << 5,
RX = 1 << 4,
DSR = 1 << 3,
DCD = 1 << 2,
CTS = 1 << 1,
RI = 1 << 0,
}
pub struct Interrupt(pub u32);
impl Interrupt {
pub const E: u32 = INT_OE | INT_BE | INT_PE | INT_FE;
pub const MS: u32 = INT_RI | INT_DSR | INT_DCD | INT_CTS;
pub const OE: Self = Self(1 << 10);
pub const BE: Self = Self(1 << 9);
pub const PE: Self = Self(1 << 8);
pub const FE: Self = Self(1 << 7);
pub const RT: Self = Self(1 << 6);
pub const TX: Self = Self(1 << 5);
pub const RX: Self = Self(1 << 4);
pub const DSR: Self = Self(1 << 3);
pub const DCD: Self = Self(1 << 2);
pub const CTS: Self = Self(1 << 1);
pub const RI: Self = Self(1 << 0);
pub const E: Self = Self(Self::OE.0 | Self::BE.0 | Self::PE.0 | Self::FE.0);
pub const MS: Self = Self(Self::RI.0 | Self::DSR.0 | Self::DCD.0 | Self::CTS.0);
}
}
+4 -21
View File
@@ -24,28 +24,11 @@ pub static PL011_OPS: MemoryRegionOps = MemoryRegionOps {
};
unsafe extern "C" fn pl011_read(opaque: *mut c_void, addr: hwaddr, size: c_uint) -> u64 {
assert!(!opaque.is_null());
let mut state = unsafe { NonNull::new_unchecked(opaque.cast::<PL011State>()) };
let val = unsafe { state.as_mut().read(addr, size) };
match val {
std::ops::ControlFlow::Break(val) => val,
std::ops::ControlFlow::Continue(val) => {
// SAFETY: self.char_backend is a valid CharBackend instance after it's been
// initialized in realize().
let cb_ptr = unsafe { core::ptr::addr_of_mut!(state.as_mut().char_backend) };
unsafe {
qemu_chr_fe_accept_input(cb_ptr);
}
val
}
}
let mut state = NonNull::new(opaque).unwrap().cast::<PL011State>();
unsafe { state.as_mut() }.read(addr, size)
}
unsafe extern "C" fn pl011_write(opaque: *mut c_void, addr: hwaddr, data: u64, _size: c_uint) {
unsafe {
assert!(!opaque.is_null());
let mut state = NonNull::new_unchecked(opaque.cast::<PL011State>());
state.as_mut().write(addr, data)
}
let mut state = NonNull::new(opaque).unwrap().cast::<PL011State>();
unsafe { state.as_mut() }.write(addr, data);
}
+2
View File
@@ -18,3 +18,5 @@ pub use crate::qom::ObjectType;
pub use crate::qom_isa;
pub use crate::sysbus::SysBusDeviceMethods;
pub use crate::vmstate::VMState;
+7 -9
View File
@@ -4,7 +4,7 @@
//! Bindings to create devices and access device functionality from Rust.
use std::ffi::CStr;
use std::{ffi::CStr, ptr::NonNull};
pub use bindings::{DeviceClass, DeviceState, Property};
@@ -23,14 +23,14 @@ pub trait DeviceImpl {
///
/// If not `None`, the parent class's `realize` method is overridden
/// with the function pointed to by `REALIZE`.
const REALIZE: Option<fn(&mut Self)> = None;
const REALIZE: Option<fn(&Self)> = None;
/// If not `None`, the parent class's `reset` method is overridden
/// with the function pointed to by `RESET`.
///
/// Rust does not yet support the three-phase reset protocol; this is
/// usually okay for leaf classes.
const RESET: Option<fn(&mut Self)> = None;
const RESET: Option<fn(&Self)> = None;
/// An array providing the properties that the user can set on the
/// device. Not a `const` because referencing statics in constants
@@ -55,9 +55,8 @@ pub trait DeviceImpl {
/// can be downcasted to type `T`. We also expect the device is
/// readable/writeable from one thread at any time.
unsafe extern "C" fn rust_realize_fn<T: DeviceImpl>(dev: *mut DeviceState, _errp: *mut *mut Error) {
assert!(!dev.is_null());
let state = dev.cast::<T>();
T::REALIZE.unwrap()(unsafe { &mut *state });
let state = NonNull::new(dev).unwrap().cast::<T>();
T::REALIZE.unwrap()(unsafe { state.as_ref() });
}
/// # Safety
@@ -66,9 +65,8 @@ unsafe extern "C" fn rust_realize_fn<T: DeviceImpl>(dev: *mut DeviceState, _errp
/// can be downcasted to type `T`. We also expect the device is
/// readable/writeable from one thread at any time.
unsafe extern "C" fn rust_reset_fn<T: DeviceImpl>(dev: *mut DeviceState) {
assert!(!dev.is_null());
let state = dev.cast::<T>();
T::RESET.unwrap()(unsafe { &mut *state });
let mut state = NonNull::new(dev).unwrap().cast::<T>();
T::RESET.unwrap()(unsafe { state.as_mut() });
}
impl<T> ClassInitImpl<DeviceClass> for T
+13 -8
View File
@@ -58,6 +58,7 @@ use std::{
fmt,
ops::{Deref, DerefMut},
os::raw::c_void,
ptr::NonNull,
};
pub use bindings::{Object, ObjectClass};
@@ -153,27 +154,34 @@ impl<T: fmt::Display + ObjectType> fmt::Display for ParentField<T> {
}
unsafe extern "C" fn rust_instance_init<T: ObjectImpl>(obj: *mut Object) {
let mut state = NonNull::new(obj).unwrap().cast::<T>();
// SAFETY: obj is an instance of T, since rust_instance_init<T>
// is called from QOM core as the instance_init function
// for class T
unsafe { T::INSTANCE_INIT.unwrap()(&mut *obj.cast::<T>()) }
unsafe {
T::INSTANCE_INIT.unwrap()(state.as_mut());
}
}
unsafe extern "C" fn rust_instance_post_init<T: ObjectImpl>(obj: *mut Object) {
let state = NonNull::new(obj).unwrap().cast::<T>();
// SAFETY: obj is an instance of T, since rust_instance_post_init<T>
// is called from QOM core as the instance_post_init function
// for class T
T::INSTANCE_POST_INIT.unwrap()(unsafe { &*obj.cast::<T>() })
T::INSTANCE_POST_INIT.unwrap()(unsafe { state.as_ref() });
}
unsafe extern "C" fn rust_class_init<T: ObjectType + ClassInitImpl<T::Class>>(
klass: *mut ObjectClass,
_data: *mut c_void,
) {
let mut klass = NonNull::new(klass)
.unwrap()
.cast::<<T as ObjectType>::Class>();
// SAFETY: klass is a T::Class, since rust_class_init<T>
// is called from QOM core as the class_init function
// for class T
T::class_init(unsafe { &mut *klass.cast::<T::Class>() })
T::class_init(unsafe { klass.as_mut() })
}
unsafe extern "C" fn drop_object<T: ObjectImpl>(obj: *mut Object) {
@@ -581,11 +589,8 @@ pub trait ClassInitImpl<T> {
/// can be downcasted to type `T`. We also expect the device is
/// readable/writeable from one thread at any time.
unsafe extern "C" fn rust_unparent_fn<T: ObjectImpl>(dev: *mut Object) {
unsafe {
assert!(!dev.is_null());
let state = core::ptr::NonNull::new_unchecked(dev.cast::<T>());
T::UNPARENT.unwrap()(state.as_ref());
}
let state = NonNull::new(dev).unwrap().cast::<T>();
T::UNPARENT.unwrap()(unsafe { state.as_ref() });
}
impl<T> ClassInitImpl<ObjectClass> for T
File diff suppressed because it is too large Load Diff
+67 -51
View File
@@ -1,13 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
use std::ptr;
/// Encapsulates the requirement that
/// `MaybeUninit::<Self>::zeroed().assume_init()` does not cause undefined
/// behavior. This trait in principle could be implemented as just:
///
/// ```
/// pub unsafe trait Zeroable: Default {
/// pub unsafe trait Zeroable {
/// const ZERO: Self = unsafe { ::core::mem::MaybeUninit::<Self>::zeroed().assume_init() };
/// }
/// ```
@@ -29,58 +27,76 @@ pub unsafe trait Zeroable: Default {
const ZERO: Self;
}
unsafe impl Zeroable for crate::bindings::Property__bindgen_ty_1 {
const ZERO: Self = Self { i: 0 };
/// A macro that acts similarly to [`core::mem::zeroed()`], only is const
///
/// ## Safety
///
/// Similar to `core::mem::zeroed()`, except this zeroes padding bits. Zeroed
/// padding usually isn't relevant to safety, but might be if a C union is used.
///
/// Just like for `core::mem::zeroed()`, an all zero byte pattern might not
/// be a valid value for a type, as is the case for references `&T` and `&mut
/// T`. Reference types trigger a (denied by default) lint and cause immediate
/// undefined behavior if the lint is ignored
///
/// ```rust compile_fail
/// use const_zero::const_zero;
/// // error: any use of this value will cause an error
/// // note: `#[deny(const_err)]` on by default
/// const STR: &str = unsafe{const_zero!(&'static str)};
/// ```
///
/// `const_zero` does not work on unsized types:
///
/// ```rust compile_fail
/// use const_zero::const_zero;
/// // error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
/// const BYTES: [u8] = unsafe{const_zero!([u8])};
/// ```
/// ## Differences with `core::mem::zeroed`
///
/// `const_zero` zeroes padding bits, while `core::mem::zeroed` doesn't
macro_rules! const_zero {
// This macro to produce a type-generic zero constant is taken from the
// const_zero crate (v0.1.1):
//
// https://docs.rs/const-zero/latest/src/const_zero/lib.rs.html
//
// and used under MIT license
($type_:ty) => {{
const TYPE_SIZE: ::core::primitive::usize = ::core::mem::size_of::<$type_>();
union TypeAsBytes {
bytes: [::core::primitive::u8; TYPE_SIZE],
inner: ::core::mem::ManuallyDrop<$type_>,
}
const ZERO_BYTES: TypeAsBytes = TypeAsBytes {
bytes: [0; TYPE_SIZE],
};
::core::mem::ManuallyDrop::<$type_>::into_inner(ZERO_BYTES.inner)
}};
}
unsafe impl Zeroable for crate::bindings::Property {
const ZERO: Self = Self {
name: ptr::null(),
info: ptr::null(),
offset: 0,
bitnr: 0,
bitmask: 0,
set_default: false,
defval: Zeroable::ZERO,
arrayoffset: 0,
arrayinfo: ptr::null(),
arrayfieldsize: 0,
link_type: ptr::null(),
/// A wrapper to implement the `Zeroable` trait through the `const_zero` macro.
macro_rules! impl_zeroable {
($type:ty) => {
unsafe impl Zeroable for $type {
const ZERO: Self = unsafe { const_zero!($type) };
}
};
}
unsafe impl Zeroable for crate::bindings::VMStateDescription {
const ZERO: Self = Self {
name: ptr::null(),
unmigratable: false,
early_setup: false,
version_id: 0,
minimum_version_id: 0,
priority: crate::bindings::MigrationPriority::MIG_PRI_DEFAULT,
pre_load: None,
post_load: None,
pre_save: None,
post_save: None,
needed: None,
dev_unplug_pending: None,
fields: ptr::null(),
subsections: ptr::null(),
};
// bindgen does not derive Default here
#[allow(clippy::derivable_impls)]
impl Default for crate::bindings::VMStateFlags {
fn default() -> Self {
Self(0)
}
}
unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_1 {
const ZERO: Self = Self {
min_access_size: 0,
max_access_size: 0,
unaligned: false,
accepts: None,
};
}
unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_2 {
const ZERO: Self = Self {
min_access_size: 0,
max_access_size: 0,
unaligned: false,
};
}
impl_zeroable!(crate::bindings::Property__bindgen_ty_1);
impl_zeroable!(crate::bindings::Property);
impl_zeroable!(crate::bindings::VMStateFlags);
impl_zeroable!(crate::bindings::VMStateField);
impl_zeroable!(crate::bindings::VMStateDescription);
impl_zeroable!(crate::bindings::MemoryRegionOps__bindgen_ty_1);
impl_zeroable!(crate::bindings::MemoryRegionOps__bindgen_ty_2);
+53 -3
View File
@@ -14,8 +14,8 @@ use qemu_api::{
cell::{self, BqlCell},
declare_properties, define_property,
prelude::*,
qdev::{DeviceImpl, DeviceState, Property},
qom::{ObjectImpl, ParentField},
qdev::{DeviceClass, DeviceImpl, DeviceState, Property},
qom::{ClassInitImpl, ObjectImpl, ParentField},
vmstate::VMStateDescription,
zeroable::Zeroable,
};
@@ -37,6 +37,10 @@ pub struct DummyState {
qom_isa!(DummyState: Object, DeviceState);
pub struct DummyClass {
parent_class: <DeviceState as ObjectType>::Class,
}
declare_properties! {
DUMMY_PROPERTIES,
define_property!(
@@ -49,7 +53,7 @@ declare_properties! {
}
unsafe impl ObjectType for DummyState {
type Class = <DeviceState as ObjectType>::Class;
type Class = DummyClass;
const TYPE_NAME: &'static CStr = c_str!("dummy");
}
@@ -67,6 +71,51 @@ impl DeviceImpl for DummyState {
}
}
// `impl<T> ClassInitImpl<DummyClass> for T` doesn't work since it violates
// orphan rule.
impl ClassInitImpl<DummyClass> for DummyState {
fn class_init(klass: &mut DummyClass) {
<Self as ClassInitImpl<DeviceClass>>::class_init(&mut klass.parent_class);
}
}
#[derive(qemu_api_macros::offsets)]
#[repr(C)]
#[derive(qemu_api_macros::Object)]
pub struct DummyChildState {
parent: ParentField<DummyState>,
}
qom_isa!(DummyChildState: Object, DeviceState, DummyState);
pub struct DummyChildClass {
parent_class: <DummyState as ObjectType>::Class,
}
unsafe impl ObjectType for DummyChildState {
type Class = DummyChildClass;
const TYPE_NAME: &'static CStr = c_str!("dummy_child");
}
impl ObjectImpl for DummyChildState {
type ParentType = DummyState;
const ABSTRACT: bool = false;
}
impl DeviceImpl for DummyChildState {}
impl ClassInitImpl<DummyClass> for DummyChildState {
fn class_init(klass: &mut DummyClass) {
<Self as ClassInitImpl<DeviceClass>>::class_init(&mut klass.parent_class);
}
}
impl ClassInitImpl<DummyChildClass> for DummyChildState {
fn class_init(klass: &mut DummyChildClass) {
<Self as ClassInitImpl<DummyClass>>::class_init(&mut klass.parent_class);
}
}
fn init_qom() {
static ONCE: BqlCell<bool> = BqlCell::new(false);
@@ -85,6 +134,7 @@ fn test_object_new() {
init_qom();
unsafe {
object_unref(object_new(DummyState::TYPE_NAME.as_ptr()).cast());
object_unref(object_new(DummyChildState::TYPE_NAME.as_ptr()).cast());
}
}
+2 -2
View File
@@ -57,8 +57,8 @@ if have_user
stub_ss.add(files('cpu-synchronize-state.c'))
# Stubs for QAPI events. Those can always be included in the build, but
# they are not built at all for --disable-system --disable-tools builds.
if not (have_system or have_tools)
# they are not built at all for --disable-system builds.
if not have_system
stub_ss.add(files('qdev.c'))
endif
endif
+155 -1
View File
@@ -1364,7 +1364,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
"taa-no", NULL, NULL, NULL,
NULL, "sbdr-ssdp-no", "fbsdp-no", "psdp-no",
NULL, "fb-clear", NULL, NULL,
NULL, NULL, NULL, NULL,
"bhi-no", NULL, NULL, NULL,
"pbrsb-no", NULL, "gds-no", "rfds-no",
"rfds-clear", NULL, NULL, NULL,
},
@@ -4547,6 +4547,160 @@ static const X86CPUDefinition builtin_x86_defs[] = {
MSR_VMX_VMFUNC_EPT_SWITCHING,
.xlevel = 0x80000008,
.model_id = "Intel Xeon Processor (SierraForest)",
.versions = (X86CPUVersionDefinition[]) {
{ .version = 1 },
{
.version = 2,
.props = (PropValue[]) {
{ "ss", "on" },
{ "tsc-adjust", "on" },
{ "cldemote", "on" },
{ "movdiri", "on" },
{ "movdir64b", "on" },
{ "gds-no", "on" },
{ "rfds-no", "on" },
{ "lam", "on" },
{ "intel-psfd", "on"},
{ "ipred-ctrl", "on"},
{ "rrsba-ctrl", "on"},
{ "bhi-ctrl", "on"},
{ "stepping", "3" },
{ /* end of list */ }
}
},
{ /* end of list */ },
},
},
{
.name = "ClearwaterForest",
.level = 0x23,
.xlevel = 0x80000008,
.vendor = CPUID_VENDOR_INTEL,
.family = 6,
.model = 221,
.stepping = 0,
/*
* please keep the ascending order so that we can have a clear view of
* bit position of each feature.
*/
.features[FEAT_1_EDX] =
CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC |
CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC |
CPUID_SEP | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV |
CPUID_PAT | CPUID_PSE36 | CPUID_CLFLUSH | CPUID_MMX | CPUID_FXSR |
CPUID_SSE | CPUID_SSE2 | CPUID_SS,
.features[FEAT_1_ECX] =
CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSSE3 |
CPUID_EXT_FMA | CPUID_EXT_CX16 | CPUID_EXT_PCID | CPUID_EXT_SSE41 |
CPUID_EXT_SSE42 | CPUID_EXT_X2APIC | CPUID_EXT_MOVBE |
CPUID_EXT_POPCNT | CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_AES |
CPUID_EXT_XSAVE | CPUID_EXT_AVX | CPUID_EXT_F16C | CPUID_EXT_RDRAND,
.features[FEAT_8000_0001_EDX] =
CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | CPUID_EXT2_PDPE1GB |
CPUID_EXT2_RDTSCP | CPUID_EXT2_LM,
.features[FEAT_8000_0001_ECX] =
CPUID_EXT3_LAHF_LM | CPUID_EXT3_ABM | CPUID_EXT3_3DNOWPREFETCH,
.features[FEAT_8000_0008_EBX] =
CPUID_8000_0008_EBX_WBNOINVD,
.features[FEAT_7_0_EBX] =
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_TSC_ADJUST |
CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP |
CPUID_7_0_EBX_CLFLUSHOPT | CPUID_7_0_EBX_CLWB |
CPUID_7_0_EBX_SHA_NI,
.features[FEAT_7_0_ECX] =
CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_GFNI |
CPUID_7_0_ECX_VAES | CPUID_7_0_ECX_VPCLMULQDQ |
CPUID_7_0_ECX_RDPID | CPUID_7_0_ECX_BUS_LOCK_DETECT |
CPUID_7_0_ECX_CLDEMOTE | CPUID_7_0_ECX_MOVDIRI |
CPUID_7_0_ECX_MOVDIR64B,
.features[FEAT_7_0_EDX] =
CPUID_7_0_EDX_FSRM | CPUID_7_0_EDX_SERIALIZE |
CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_ARCH_CAPABILITIES |
CPUID_7_0_EDX_SPEC_CTRL_SSBD,
.features[FEAT_ARCH_CAPABILITIES] =
MSR_ARCH_CAP_RDCL_NO | MSR_ARCH_CAP_IBRS_ALL |
MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY | MSR_ARCH_CAP_MDS_NO |
MSR_ARCH_CAP_PSCHANGE_MC_NO | MSR_ARCH_CAP_SBDR_SSDP_NO |
MSR_ARCH_CAP_FBSDP_NO | MSR_ARCH_CAP_PSDP_NO |
MSR_ARCH_CAP_BHI_NO | MSR_ARCH_CAP_PBRSB_NO |
MSR_ARCH_CAP_GDS_NO | MSR_ARCH_CAP_RFDS_NO,
.features[FEAT_XSAVE] =
CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC |
CPUID_XSAVE_XGETBV1 | CPUID_XSAVE_XSAVES,
.features[FEAT_6_EAX] =
CPUID_6_EAX_ARAT,
.features[FEAT_7_1_EAX] =
CPUID_7_1_EAX_SHA512 | CPUID_7_1_EAX_SM3 | CPUID_7_1_EAX_SM4 |
CPUID_7_1_EAX_AVX_VNNI | CPUID_7_1_EAX_CMPCCXADD |
CPUID_7_1_EAX_FSRS | CPUID_7_1_EAX_AVX_IFMA |
CPUID_7_1_EAX_LAM,
.features[FEAT_7_1_EDX] =
CPUID_7_1_EDX_AVX_VNNI_INT8 | CPUID_7_1_EDX_AVX_NE_CONVERT |
CPUID_7_1_EDX_AVX_VNNI_INT16 | CPUID_7_1_EDX_PREFETCHITI,
.features[FEAT_7_2_EDX] =
CPUID_7_2_EDX_PSFD | CPUID_7_2_EDX_IPRED_CTRL |
CPUID_7_2_EDX_RRSBA_CTRL | CPUID_7_2_EDX_DDPD_U |
CPUID_7_2_EDX_BHI_CTRL | CPUID_7_2_EDX_MCDT_NO,
.features[FEAT_VMX_BASIC] =
MSR_VMX_BASIC_INS_OUTS | MSR_VMX_BASIC_TRUE_CTLS,
.features[FEAT_VMX_ENTRY_CTLS] =
VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_IA32E_MODE |
VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL |
VMX_VM_ENTRY_LOAD_IA32_PAT | VMX_VM_ENTRY_LOAD_IA32_EFER,
.features[FEAT_VMX_EPT_VPID_CAPS] =
MSR_VMX_EPT_EXECONLY | MSR_VMX_EPT_PAGE_WALK_LENGTH_4 |
MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | MSR_VMX_EPT_1GB |
MSR_VMX_EPT_INVEPT | MSR_VMX_EPT_AD_BITS |
MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT |
MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR |
MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT |
MSR_VMX_EPT_INVVPID_ALL_CONTEXT |
MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS,
.features[FEAT_VMX_EXIT_CTLS] =
VMX_VM_EXIT_SAVE_DEBUG_CONTROLS |
VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL |
VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_IA32_PAT |
VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER |
VMX_VM_EXIT_LOAD_IA32_EFER | VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER,
.features[FEAT_VMX_MISC] =
MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_ACTIVITY_HLT |
MSR_VMX_MISC_VMWRITE_VMEXIT,
.features[FEAT_VMX_PINBASED_CTLS] =
VMX_PIN_BASED_EXT_INTR_MASK | VMX_PIN_BASED_NMI_EXITING |
VMX_PIN_BASED_VIRTUAL_NMIS | VMX_PIN_BASED_VMX_PREEMPTION_TIMER |
VMX_PIN_BASED_POSTED_INTR,
.features[FEAT_VMX_PROCBASED_CTLS] =
VMX_CPU_BASED_VIRTUAL_INTR_PENDING |
VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING |
VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING |
VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING |
VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING |
VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING |
VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_VIRTUAL_NMI_PENDING |
VMX_CPU_BASED_MOV_DR_EXITING | VMX_CPU_BASED_UNCOND_IO_EXITING |
VMX_CPU_BASED_USE_IO_BITMAPS | VMX_CPU_BASED_MONITOR_TRAP_FLAG |
VMX_CPU_BASED_USE_MSR_BITMAPS | VMX_CPU_BASED_MONITOR_EXITING |
VMX_CPU_BASED_PAUSE_EXITING |
VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS,
.features[FEAT_VMX_SECONDARY_CTLS] =
VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
VMX_SECONDARY_EXEC_ENABLE_EPT | VMX_SECONDARY_EXEC_DESC |
VMX_SECONDARY_EXEC_RDTSCP |
VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_WBINVD_EXITING |
VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST |
VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT |
VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
VMX_SECONDARY_EXEC_RDRAND_EXITING |
VMX_SECONDARY_EXEC_ENABLE_INVPCID |
VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS |
VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML |
VMX_SECONDARY_EXEC_XSAVES,
.features[FEAT_VMX_VMFUNC] =
MSR_VMX_VMFUNC_EPT_SWITCHING,
.model_id = "Intel Xeon Processor (ClearwaterForest)",
.versions = (X86CPUVersionDefinition[]) {
{ .version = 1 },
{ /* end of list */ },
+27 -6
View File
@@ -951,6 +951,12 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU *cpu, FeatureWord w);
/* Speculative Store Bypass Disable */
#define CPUID_7_0_EDX_SPEC_CTRL_SSBD (1U << 31)
/* SHA512 Instruction */
#define CPUID_7_1_EAX_SHA512 (1U << 0)
/* SM3 Instruction */
#define CPUID_7_1_EAX_SM3 (1U << 1)
/* SM4 Instruction */
#define CPUID_7_1_EAX_SM4 (1U << 2)
/* AVX VNNI Instruction */
#define CPUID_7_1_EAX_AVX_VNNI (1U << 4)
/* AVX512 BFloat16 Instruction */
@@ -963,6 +969,12 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU *cpu, FeatureWord w);
#define CPUID_7_1_EAX_FSRS (1U << 11)
/* Fast Short REP CMPS/SCAS */
#define CPUID_7_1_EAX_FSRC (1U << 12)
/* Flexible return and event delivery (FRED) */
#define CPUID_7_1_EAX_FRED (1U << 17)
/* Load into IA32_KERNEL_GS_BASE (LKGS) */
#define CPUID_7_1_EAX_LKGS (1U << 18)
/* Non-Serializing Write to Model Specific Register (WRMSRNS) */
#define CPUID_7_1_EAX_WRMSRNS (1U << 19)
/* Support Tile Computational Operations on FP16 Numbers */
#define CPUID_7_1_EAX_AMX_FP16 (1U << 21)
/* Support for VPMADD52[H,L]UQ */
@@ -976,17 +988,23 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU *cpu, FeatureWord w);
#define CPUID_7_1_EDX_AVX_NE_CONVERT (1U << 5)
/* AMX COMPLEX Instructions */
#define CPUID_7_1_EDX_AMX_COMPLEX (1U << 8)
/* AVX-VNNI-INT16 Instructions */
#define CPUID_7_1_EDX_AVX_VNNI_INT16 (1U << 10)
/* PREFETCHIT0/1 Instructions */
#define CPUID_7_1_EDX_PREFETCHITI (1U << 14)
/* Support for Advanced Vector Extensions 10 */
#define CPUID_7_1_EDX_AVX10 (1U << 19)
/* Flexible return and event delivery (FRED) */
#define CPUID_7_1_EAX_FRED (1U << 17)
/* Load into IA32_KERNEL_GS_BASE (LKGS) */
#define CPUID_7_1_EAX_LKGS (1U << 18)
/* Non-Serializing Write to Model Specific Register (WRMSRNS) */
#define CPUID_7_1_EAX_WRMSRNS (1U << 19)
/* Indicate bit 7 of the IA32_SPEC_CTRL MSR is supported */
#define CPUID_7_2_EDX_PSFD (1U << 0)
/* Indicate bits 3 and 4 of the IA32_SPEC_CTRL MSR are supported */
#define CPUID_7_2_EDX_IPRED_CTRL (1U << 1)
/* Indicate bits 5 and 6 of the IA32_SPEC_CTRL MSR are supported */
#define CPUID_7_2_EDX_RRSBA_CTRL (1U << 2)
/* Indicate bit 8 of the IA32_SPEC_CTRL MSR is supported */
#define CPUID_7_2_EDX_DDPD_U (1U << 3)
/* Indicate bit 10 of the IA32_SPEC_CTRL MSR is supported */
#define CPUID_7_2_EDX_BHI_CTRL (1U << 4)
/* Do not exhibit MXCSR Configuration Dependent Timing (MCDT) behavior */
#define CPUID_7_2_EDX_MCDT_NO (1U << 5)
@@ -1144,7 +1162,10 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU *cpu, FeatureWord w);
#define MSR_ARCH_CAP_FBSDP_NO (1U << 14)
#define MSR_ARCH_CAP_PSDP_NO (1U << 15)
#define MSR_ARCH_CAP_FB_CLEAR (1U << 17)
#define MSR_ARCH_CAP_BHI_NO (1U << 20)
#define MSR_ARCH_CAP_PBRSB_NO (1U << 24)
#define MSR_ARCH_CAP_GDS_NO (1U << 26)
#define MSR_ARCH_CAP_RFDS_NO (1U << 27)
#define MSR_CORE_CAP_SPLIT_LOCK_DETECT (1U << 5)
+15 -40
View File
@@ -1630,7 +1630,7 @@ static void gen_CMC(DisasContext *s, X86DecodedInsn *decode)
static void gen_CMOVcc(DisasContext *s, X86DecodedInsn *decode)
{
gen_cmovcc1(s, decode->b & 0xf, s->T0, s->T1);
gen_cmovcc(s, decode->b & 0xf, s->T0, s->T1);
}
static void gen_CMPccXADD(DisasContext *s, X86DecodedInsn *decode)
@@ -1739,11 +1739,7 @@ static void gen_CMPccXADD(DisasContext *s, X86DecodedInsn *decode)
static void gen_CMPS(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[2].ot;
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
gen_repz_nz(s, ot, gen_cmps);
} else {
gen_cmps(s, ot);
}
gen_repz_nz(s, ot, gen_cmps);
}
static void gen_CMPXCHG(DisasContext *s, X86DecodedInsn *decode)
@@ -2234,11 +2230,7 @@ static void gen_INS(DisasContext *s, X86DecodedInsn *decode)
}
translator_io_start(&s->base);
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
gen_repz(s, ot, gen_ins);
} else {
gen_ins(s, ot);
}
gen_repz(s, ot, gen_ins);
}
static void gen_INSERTQ_i(DisasContext *s, X86DecodedInsn *decode)
@@ -2293,8 +2285,11 @@ static void gen_IRET(DisasContext *s, X86DecodedInsn *decode)
static void gen_Jcc(DisasContext *s, X86DecodedInsn *decode)
{
TCGLabel *taken = gen_new_label();
gen_bnd_jmp(s);
gen_jcc(s, decode->b & 0xf, decode->immediate);
gen_jcc(s, decode->b & 0xf, taken);
gen_conditional_jump_labels(s, decode->immediate, NULL, taken);
}
static void gen_JCXZ(DisasContext *s, X86DecodedInsn *decode)
@@ -2419,11 +2414,7 @@ static void gen_LGS(DisasContext *s, X86DecodedInsn *decode)
static void gen_LODS(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[1].ot;
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
gen_repz(s, ot, gen_lods);
} else {
gen_lods(s, ot);
}
gen_repz(s, ot, gen_lods);
}
static void gen_LOOP(DisasContext *s, X86DecodedInsn *decode)
@@ -2444,7 +2435,7 @@ static void gen_LOOPE(DisasContext *s, X86DecodedInsn *decode)
gen_update_cc_op(s);
gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
gen_op_jz_ecx(s, not_taken);
gen_jcc1(s, (JCC_Z << 1), taken); /* jz taken */
gen_jcc(s, (JCC_Z << 1), taken); /* jz taken */
gen_conditional_jump_labels(s, decode->immediate, not_taken, taken);
}
@@ -2456,7 +2447,7 @@ static void gen_LOOPNE(DisasContext *s, X86DecodedInsn *decode)
gen_update_cc_op(s);
gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
gen_op_jz_ecx(s, not_taken);
gen_jcc1(s, (JCC_Z << 1) | 1, taken); /* jnz taken */
gen_jcc(s, (JCC_Z << 1) | 1, taken); /* jnz taken */
gen_conditional_jump_labels(s, decode->immediate, not_taken, taken);
}
@@ -2621,11 +2612,7 @@ static void gen_MOVq_dq(DisasContext *s, X86DecodedInsn *decode)
static void gen_MOVS(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[2].ot;
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
gen_repz(s, ot, gen_movs);
} else {
gen_movs(s, ot);
}
gen_repz(s, ot, gen_movs);
}
static void gen_MUL(DisasContext *s, X86DecodedInsn *decode)
@@ -2787,11 +2774,7 @@ static void gen_OUTS(DisasContext *s, X86DecodedInsn *decode)
}
translator_io_start(&s->base);
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
gen_repz(s, ot, gen_outs);
} else {
gen_outs(s, ot);
}
gen_repz(s, ot, gen_outs);
}
static void gen_PALIGNR(DisasContext *s, X86DecodedInsn *decode)
@@ -3872,16 +3855,12 @@ static void gen_SBB(DisasContext *s, X86DecodedInsn *decode)
static void gen_SCAS(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[2].ot;
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
gen_repz_nz(s, ot, gen_scas);
} else {
gen_scas(s, ot);
}
gen_repz_nz(s, ot, gen_scas);
}
static void gen_SETcc(DisasContext *s, X86DecodedInsn *decode)
{
gen_setcc1(s, decode->b & 0xf, s->T0);
gen_setcc(s, decode->b & 0xf, s->T0);
}
static void gen_SFENCE(DisasContext *s, X86DecodedInsn *decode)
@@ -4082,11 +4061,7 @@ static void gen_STMXCSR(DisasContext *s, X86DecodedInsn *decode)
static void gen_STOS(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[1].ot;
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
gen_repz(s, ot, gen_stos);
} else {
gen_stos(s, ot);
}
gen_repz(s, ot, gen_stos);
}
static void gen_SUB(DisasContext *s, X86DecodedInsn *decode)
File diff suppressed because it is too large Load Diff