mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
arch: FeatureMsrAdjustment type
We introduce a type analogous to CpuidOutputRegisterAdjustment, but for feature MSRs. Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de> On-behalf-of: SAP oliver.anderson@sap.com
This commit is contained in:
committed by
Rob Bradford
parent
37aa545c2a
commit
26305445b6
@@ -3,9 +3,14 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
//
|
//
|
||||||
|
|
||||||
|
use hypervisor::arch::x86::MsrEntry;
|
||||||
|
use log::{debug, error};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::x86_64::helpers::{deserialize_u32_hex, serialize_u32_hex};
|
use crate::x86_64::Error;
|
||||||
|
use crate::x86_64::helpers::{
|
||||||
|
deserialize_u32_hex, deserialize_u64_hex, serialize_u32_hex, serialize_u64_hex,
|
||||||
|
};
|
||||||
|
|
||||||
/// The register address of an MSR
|
/// The register address of an MSR
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
@@ -16,3 +21,71 @@ pub struct RegisterAddress(
|
|||||||
)]
|
)]
|
||||||
pub u32,
|
pub u32,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Used to adjust the value of a Feature MSR.
|
||||||
|
///
|
||||||
|
/// Instances of this struct typically adjust MSR values according to the
|
||||||
|
/// following formula: `msr_value = (self.mask & msr_value) | self.replacements`.
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct FeatureMsrAdjustment {
|
||||||
|
/// Packs values to be placed into the given feature MSR value.
|
||||||
|
#[serde(
|
||||||
|
serialize_with = "serialize_u64_hex",
|
||||||
|
deserialize_with = "deserialize_u64_hex"
|
||||||
|
)]
|
||||||
|
pub replacements: u64,
|
||||||
|
|
||||||
|
/// Used to zero out the area `replacements` occupy. This mask is not necessarily !replacements, as replacements
|
||||||
|
/// may pack values of different types that occupy varying ranges of bits.
|
||||||
|
///
|
||||||
|
/// Bit ranges within a feature MSR value that are **not** supposed to be replaced/overwritten should be set in
|
||||||
|
/// this mask.
|
||||||
|
#[serde(
|
||||||
|
serialize_with = "serialize_u64_hex",
|
||||||
|
deserialize_with = "deserialize_u64_hex"
|
||||||
|
)]
|
||||||
|
pub mask: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FeatureMsrAdjustment {
|
||||||
|
/// Adjusts the given `feature_msrs` according to `adjustments`.
|
||||||
|
///
|
||||||
|
/// An error is returned if there exists an MSR register address in
|
||||||
|
/// `adjustments` without a matching entry in `feature_msrs`.
|
||||||
|
pub(super) fn adjust_feature_msrs(
|
||||||
|
feature_msrs: &[MsrEntry],
|
||||||
|
adjustments: &[(RegisterAddress, FeatureMsrAdjustment)],
|
||||||
|
) -> Result<Vec<MsrEntry>, Error> {
|
||||||
|
let mut missing_msr = false;
|
||||||
|
let mut output_feature_msrs = Vec::with_capacity(adjustments.len());
|
||||||
|
for (reg_address, adjustment) in adjustments {
|
||||||
|
let Some(entry) = feature_msrs
|
||||||
|
.iter()
|
||||||
|
.find(|entry| entry.index == reg_address.0)
|
||||||
|
else {
|
||||||
|
missing_msr = true;
|
||||||
|
error!(
|
||||||
|
"Did not find feature based MSR entry for MSR {:#x}",
|
||||||
|
reg_address.0
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut entry = *entry;
|
||||||
|
let data = entry.data;
|
||||||
|
entry.data = (adjustment.mask & data) | adjustment.replacements;
|
||||||
|
|
||||||
|
debug!(
|
||||||
|
"Prepared adjusted MSR feature: register address={:#x} value={:#x}, previous value={data:#x}",
|
||||||
|
entry.index, entry.data
|
||||||
|
);
|
||||||
|
output_feature_msrs.push(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if missing_msr {
|
||||||
|
Err(Error::CpuProfileMissingMsr)
|
||||||
|
} else {
|
||||||
|
Ok(output_feature_msrs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -170,6 +170,13 @@ pub enum Error {
|
|||||||
)]
|
)]
|
||||||
MissingExpectedCpuidEntry(#[source] MissingCpuidEntriesError),
|
MissingExpectedCpuidEntry(#[source] MissingCpuidEntriesError),
|
||||||
|
|
||||||
|
/// Error when trying to apply a CPU profile because a necessary MSR was not found.
|
||||||
|
///
|
||||||
|
/// We encourage functions returning this variant to log all missing MSRs for debugging
|
||||||
|
/// purposes.
|
||||||
|
#[error("The selected CPU profile cannot be utilized because a necessary MSR was not found")]
|
||||||
|
CpuProfileMissingMsr,
|
||||||
|
|
||||||
// Error writing EBDA address
|
// Error writing EBDA address
|
||||||
#[error("Error writing EBDA address")]
|
#[error("Error writing EBDA address")]
|
||||||
EbdaSetup(#[source] vm_memory::GuestMemoryError),
|
EbdaSetup(#[source] vm_memory::GuestMemoryError),
|
||||||
|
|||||||
Reference in New Issue
Block a user