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:
Daniel Verkamp 2022-11-22 15:38:02 -08:00 committed by crosvm LUCI
parent 2eb36ff983
commit a444d2592e
2 changed files with 39 additions and 49 deletions

View file

@ -1066,8 +1066,11 @@ where
/// Wrap read_allow and write_allow to store them in MsrHandlers level. /// Wrap read_allow and write_allow to store them in MsrHandlers level.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum MsrRWType { pub enum MsrRWType {
#[serde(rename = "r")]
ReadOnly, ReadOnly,
#[serde(rename = "w")]
WriteOnly, WriteOnly,
#[serde(rename = "rw", alias = "wr")]
ReadWrite, ReadWrite,
} }
@ -1076,9 +1079,11 @@ pub enum MsrRWType {
pub enum MsrAction { pub enum MsrAction {
/// Read and write from host directly, and the control of MSR will /// Read and write from host directly, and the control of MSR will
/// take effect on host. /// take effect on host.
#[serde(rename = "pass")]
MsrPassthrough, MsrPassthrough,
/// Store the dummy value for msr (copy from host or custom values), /// Store the dummy value for msr (copy from host or custom values),
/// and the control(WRMSR) of MSR won't take effect on host. /// and the control(WRMSR) of MSR won't take effect on host.
#[serde(rename = "emu")]
MsrEmulate, MsrEmulate,
} }
@ -1089,9 +1094,11 @@ pub enum MsrAction {
pub enum MsrValueFrom { pub enum MsrValueFrom {
/// Read/write MSR value from/into CPU 0. /// Read/write MSR value from/into CPU 0.
/// The MSR source CPU always be CPU 0. /// The MSR source CPU always be CPU 0.
#[serde(rename = "cpu0")]
RWFromCPU0, RWFromCPU0,
/// Read/write MSR value from/into the running CPU. /// Read/write MSR value from/into the running CPU.
/// If vCPU migrates to another pcpu, the MSR source CPU will also change. /// If vCPU migrates to another pcpu, the MSR source CPU will also change.
#[serde(skip)]
RWFromRunningCPU, RWFromRunningCPU,
} }
@ -1099,9 +1106,11 @@ pub enum MsrValueFrom {
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum MsrFilter { pub enum MsrFilter {
/// Leave it to hypervisor (KVM) default. /// Leave it to hypervisor (KVM) default.
#[serde(rename = "no")]
Default, Default,
/// Don't let KVM do the default thing and use our userspace MSR /// Don't let KVM do the default thing and use our userspace MSR
/// implementation. /// implementation.
#[serde(rename = "yes")]
Override, Override,
} }

View file

@ -589,60 +589,41 @@ pub fn parse_mmio_address_range(s: &str) -> Result<Vec<AddressRange>, String> {
.collect() .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"))] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn parse_userspace_msr_options(value: &str) -> Result<(u32, MsrConfig), String> { pub fn parse_userspace_msr_options(value: &str) -> Result<(u32, MsrConfig), String> {
let mut rw_type: Option<MsrRWType> = None; let options: UserspaceMsrOptions = from_key_values(value)?;
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"))?;
Ok(( Ok((
index, options.index,
MsrConfig { MsrConfig {
rw_type, rw_type: options.rw_type,
action, action: options.action,
from, from: options.from,
filter, filter: options.filter,
}, },
)) ))
} }