mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-09 03:57:24 +00:00
config: parse --userspace-msr with serde_keyvalue
This removes the last caller of parse_key_value_options(). BUG=b:255223604 TEST=cargo test Change-Id: Ia17eb320094ee3d46f0db238f2077163e257b7f8 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/4049037 Reviewed-by: Alexandre Courbot <acourbot@chromium.org> Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
parent
2eb36ff983
commit
a444d2592e
2 changed files with 39 additions and 49 deletions
|
@ -1066,8 +1066,11 @@ where
|
|||
/// Wrap read_allow and write_allow to store them in MsrHandlers level.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum MsrRWType {
|
||||
#[serde(rename = "r")]
|
||||
ReadOnly,
|
||||
#[serde(rename = "w")]
|
||||
WriteOnly,
|
||||
#[serde(rename = "rw", alias = "wr")]
|
||||
ReadWrite,
|
||||
}
|
||||
|
||||
|
@ -1076,9 +1079,11 @@ pub enum MsrRWType {
|
|||
pub enum MsrAction {
|
||||
/// Read and write from host directly, and the control of MSR will
|
||||
/// take effect on host.
|
||||
#[serde(rename = "pass")]
|
||||
MsrPassthrough,
|
||||
/// Store the dummy value for msr (copy from host or custom values),
|
||||
/// and the control(WRMSR) of MSR won't take effect on host.
|
||||
#[serde(rename = "emu")]
|
||||
MsrEmulate,
|
||||
}
|
||||
|
||||
|
@ -1089,9 +1094,11 @@ pub enum MsrAction {
|
|||
pub enum MsrValueFrom {
|
||||
/// Read/write MSR value from/into CPU 0.
|
||||
/// The MSR source CPU always be CPU 0.
|
||||
#[serde(rename = "cpu0")]
|
||||
RWFromCPU0,
|
||||
/// Read/write MSR value from/into the running CPU.
|
||||
/// If vCPU migrates to another pcpu, the MSR source CPU will also change.
|
||||
#[serde(skip)]
|
||||
RWFromRunningCPU,
|
||||
}
|
||||
|
||||
|
@ -1099,9 +1106,11 @@ pub enum MsrValueFrom {
|
|||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum MsrFilter {
|
||||
/// Leave it to hypervisor (KVM) default.
|
||||
#[serde(rename = "no")]
|
||||
Default,
|
||||
/// Don't let KVM do the default thing and use our userspace MSR
|
||||
/// implementation.
|
||||
#[serde(rename = "yes")]
|
||||
Override,
|
||||
}
|
||||
|
||||
|
|
|
@ -589,60 +589,41 @@ pub fn parse_mmio_address_range(s: &str) -> Result<Vec<AddressRange>, String> {
|
|||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
#[derive(Deserialize, Serialize, serde_keyvalue::FromKeyValues)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct UserspaceMsrOptions {
|
||||
pub index: u32,
|
||||
#[serde(rename = "type")]
|
||||
pub rw_type: MsrRWType,
|
||||
pub action: MsrAction,
|
||||
#[serde(default = "default_msr_value_from")]
|
||||
pub from: MsrValueFrom,
|
||||
#[serde(default = "default_msr_filter")]
|
||||
pub filter: MsrFilter,
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
fn default_msr_value_from() -> MsrValueFrom {
|
||||
MsrValueFrom::RWFromRunningCPU
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
fn default_msr_filter() -> MsrFilter {
|
||||
MsrFilter::Default
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
pub fn parse_userspace_msr_options(value: &str) -> Result<(u32, MsrConfig), String> {
|
||||
let mut rw_type: Option<MsrRWType> = None;
|
||||
let mut action: Option<MsrAction> = None;
|
||||
let mut from = MsrValueFrom::RWFromRunningCPU;
|
||||
let mut filter = MsrFilter::Default;
|
||||
|
||||
let mut options = super::argument::parse_key_value_options("userspace-msr", value, ',');
|
||||
let index: u32 = options
|
||||
.next()
|
||||
.ok_or(String::from("userspace-msr: expected index"))?
|
||||
.key_numeric()
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
for opt in options {
|
||||
match opt.key() {
|
||||
"type" => match opt.value().map_err(|e| e.to_string())? {
|
||||
"r" => rw_type = Some(MsrRWType::ReadOnly),
|
||||
"w" => rw_type = Some(MsrRWType::WriteOnly),
|
||||
"rw" | "wr" => rw_type = Some(MsrRWType::ReadWrite),
|
||||
_ => {
|
||||
return Err(String::from("bad type"));
|
||||
}
|
||||
},
|
||||
"action" => match opt.value().map_err(|e| e.to_string())? {
|
||||
"pass" => action = Some(MsrAction::MsrPassthrough),
|
||||
"emu" => action = Some(MsrAction::MsrEmulate),
|
||||
_ => return Err(String::from("bad action")),
|
||||
},
|
||||
"from" => match opt.value().map_err(|e| e.to_string())? {
|
||||
"cpu0" => from = MsrValueFrom::RWFromCPU0,
|
||||
_ => return Err(String::from("bad from")),
|
||||
},
|
||||
"filter" => match opt.value().map_err(|e| e.to_string())? {
|
||||
"yes" => filter = MsrFilter::Override,
|
||||
"no" => filter = MsrFilter::Default,
|
||||
_ => return Err(String::from("bad filter")),
|
||||
},
|
||||
|
||||
_ => return Err(opt.invalid_key_err().to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
let rw_type = rw_type.ok_or(String::from("userspace-msr: type is required"))?;
|
||||
|
||||
let action = action.ok_or(String::from("userspace-msr: action is required"))?;
|
||||
let options: UserspaceMsrOptions = from_key_values(value)?;
|
||||
|
||||
Ok((
|
||||
index,
|
||||
options.index,
|
||||
MsrConfig {
|
||||
rw_type,
|
||||
action,
|
||||
from,
|
||||
filter,
|
||||
rw_type: options.rw_type,
|
||||
action: options.action,
|
||||
from: options.from,
|
||||
filter: options.filter,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue