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
* 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:
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
+293
-222
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -18,3 +18,5 @@ pub use crate::qom::ObjectType;
|
||||
pub use crate::qom_isa;
|
||||
|
||||
pub use crate::sysbus::SysBusDeviceMethods;
|
||||
|
||||
pub use crate::vmstate::VMState;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+444
-256
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
+212
-151
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user