Skip to content

Commit a86a87b

Browse files
zulinx86ShadowCurse
andcommitted
refactor(vmm): 2-step CpuConfiguration build for aarch64
As done in x86_64, build a custom `CpuConfiguration` with 2 steps: 1. Construct a base `CpuConfiguration`. 2. Apply CPU template to the default `CpuConfiguration`. By providing the same interface between x86_64 and aarch64, it becomes possible to unify some operations. Signed-off-by: Takahiro Itazuri <[email protected]> Co-authored-by: Egor Lazarchuk <[email protected]>
1 parent 45f4b10 commit a86a87b

File tree

5 files changed

+43
-63
lines changed

5 files changed

+43
-63
lines changed

src/vmm/src/arch/aarch64/regs.rs

+3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ pub enum Error {
5151
/// Failed to get a register value.
5252
#[error("Failed to get register {0}: {1}")]
5353
GetOneReg(u64, kvm_ioctls::Error),
54+
/// Failed to set a register value.
55+
#[error("Failed to set register {0}: {1}")]
56+
SetOneReg(u64, kvm_ioctls::Error),
5457
/// Failed to get the register list.
5558
#[error("Failed to retrieve list of registers: {0}")]
5659
GetRegList(kvm_ioctls::Error),

src/vmm/src/builder.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -840,9 +840,17 @@ pub fn configure_system_for_boot(
840840
}
841841
#[cfg(target_arch = "aarch64")]
842842
{
843-
let cpu_config = crate::guest_config::aarch64::CpuConfiguration::new(
844-
&vcpus[0].kvm_vcpu.fd,
845-
&vm_config.cpu_template,
843+
// Construct the base CpuConfiguration to apply CPU template onto.
844+
let regs = vcpus[0]
845+
.kvm_vcpu
846+
.get_regs(&cpu_template.reg_list())
847+
.map_err(GuestConfigError)?;
848+
let cpu_config = crate::guest_config::aarch64::CpuConfiguration { regs };
849+
850+
// Apply CPU template to the base CpuConfiguration.
851+
let cpu_config = crate::guest_config::aarch64::CpuConfiguration::apply_template(
852+
cpu_config,
853+
&cpu_template,
846854
)?;
847855

848856
let vcpu_config = VcpuConfig {

src/vmm/src/guest_config/aarch64/mod.rs

+6-47
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,15 @@
44
/// Module with CPU templates for aarch64
55
pub mod static_cpu_templates;
66

7-
use kvm_ioctls::VcpuFd;
87
pub use static_cpu_templates::*;
98

10-
use super::templates::{CpuTemplateType, CustomCpuTemplate};
9+
use super::templates::CustomCpuTemplate;
1110
use crate::arch::regs::{Aarch64Register, Error as ArchError};
1211

1312
/// Errors thrown while configuring templates.
1413
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
1514
#[error("Failed to create a guest cpu configuration: {0}")]
16-
pub struct Error(#[from] ArchError);
15+
pub struct Error(#[from] pub ArchError);
1716

1817
/// CPU configuration for aarch64
1918
#[derive(Debug, Default, Clone, PartialEq, Eq)]
@@ -24,56 +23,16 @@ pub struct CpuConfiguration {
2423

2524
impl CpuConfiguration {
2625
/// Creates new guest CPU config based on the provided template
27-
pub fn new(vcpu: &VcpuFd, template: &Option<CpuTemplateType>) -> Result<Self, Error> {
28-
match template {
29-
Some(ref cpu_template) => Self::with_template(vcpu, cpu_template),
30-
None => Ok(Self::default()),
26+
pub fn apply_template(mut self, template: &CustomCpuTemplate) -> Result<Self, Error> {
27+
for (modifier, reg) in template.reg_modifiers.iter().zip(self.regs.iter_mut()) {
28+
reg.value = modifier.bitmap.apply(reg.value);
3129
}
32-
}
33-
34-
/// Creates new guest CPU config based on the provided template
35-
fn with_template(vcpu: &VcpuFd, template: &CpuTemplateType) -> Result<Self, Error> {
36-
match template {
37-
CpuTemplateType::Custom(template) => Self::with_applied_template(vcpu, template),
38-
CpuTemplateType::Static(StaticCpuTemplate::V1N1) => {
39-
let template = static_cpu_templates::v1n1::v1n1();
40-
Self::with_applied_template(vcpu, &template)
41-
}
42-
_ => unreachable!("Options other than V1N1 are invalid"),
43-
}
44-
}
45-
46-
/// Creates new guest CPU config based on the provided template
47-
fn with_applied_template(vcpu: &VcpuFd, template: &CustomCpuTemplate) -> Result<Self, Error> {
48-
let regs = template
49-
.reg_modifiers
50-
.iter()
51-
.map(|modifier| {
52-
vcpu.get_one_reg(modifier.addr)
53-
.map(|value| Aarch64Register {
54-
id: modifier.addr,
55-
value: modifier.bitmap.apply(value),
56-
})
57-
.map_err(|e| Error(ArchError::GetSysRegister(modifier.addr, e)))
58-
})
59-
.collect::<Result<Vec<_>, Error>>()?;
60-
61-
Ok(Self { regs })
30+
Ok(self)
6231
}
6332

6433
/// Returns ids of registers that are changed
6534
/// by this template
6635
pub fn register_ids(&self) -> Vec<u64> {
6736
self.regs.iter().map(|reg| reg.id).collect()
6837
}
69-
70-
/// Applies cpu template to vcpu
71-
/// Used inside Vcpu to configure it
72-
pub fn apply(&self, vcpu: &VcpuFd) -> Result<(), ArchError> {
73-
for Aarch64Register { id, value } in self.regs.iter() {
74-
vcpu.set_one_reg(*id, *value)
75-
.map_err(|error| ArchError::SetSysRegister(*id, error))?;
76-
}
77-
Ok(())
78-
}
7938
}

src/vmm/src/guest_config/templates/aarch64.rs

+10
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,16 @@ where
168168
Ok(deserialized_number)
169169
}
170170

171+
impl CustomCpuTemplate {
172+
/// Get a list of register IDs that are modified by the CPU template.
173+
pub fn reg_list(&self) -> Vec<u64> {
174+
self.reg_modifiers
175+
.iter()
176+
.map(|modifier| modifier.addr)
177+
.collect()
178+
}
179+
}
180+
171181
// TODO mark with #[cfg(test)] when we combine all crates into
172182
// one firecracker crate
173183
impl CustomCpuTemplate {

src/vmm/src/vstate/vcpu/aarch64.rs

+13-13
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@ use versionize_derive::Versionize;
1414
use vm_memory::{Address, GuestAddress, GuestMemoryMmap};
1515

1616
use crate::arch::aarch64::regs::Aarch64Register;
17-
use crate::arch::regs::Error as ArchError;
1817
use crate::arch::regs::{
1918
get_mpstate, read_mpidr, restore_registers, save_core_registers, save_registers,
20-
save_system_registers, set_mpstate,
19+
save_system_registers, set_mpstate, Error as ArchError,
2120
};
2221
use crate::vcpu::VcpuConfig;
2322
use crate::vstate::vcpu::VcpuEmulation;
@@ -27,19 +26,19 @@ use crate::vstate::vm::Vm;
2726
#[derive(Debug, thiserror::Error)]
2827
pub enum Error {
2928
#[error("Error configuring the vcpu registers: {0}")]
30-
ConfigureRegisters(crate::arch::aarch64::regs::Error),
29+
ConfigureRegisters(ArchError),
3130
#[error("Error creating vcpu: {0}")]
3231
CreateVcpu(kvm_ioctls::Error),
3332
#[error("Error getting the vcpu preferred target: {0}")]
3433
GetPreferredTarget(kvm_ioctls::Error),
3534
#[error("Error initializing the vcpu: {0}")]
3635
Init(kvm_ioctls::Error),
37-
#[error("Error applying template to the vcpu: {0}")]
38-
ApplyCpuTemplate(crate::arch::aarch64::regs::Error),
36+
#[error("Error applying template: {0}")]
37+
ApplyCpuTemplate(ArchError),
3938
#[error("Failed to restore the state of the vcpu: {0}")]
40-
RestoreState(crate::arch::aarch64::regs::Error),
39+
RestoreState(ArchError),
4140
#[error("Failed to save the state of the vcpu: {0}")]
42-
SaveState(crate::arch::aarch64::regs::Error),
41+
SaveState(ArchError),
4342
}
4443

4544
type Result<T> = result::Result<T, Error>;
@@ -97,6 +96,13 @@ impl KvmVcpu {
9796
kernel_load_addr: GuestAddress,
9897
vcpu_config: &VcpuConfig,
9998
) -> std::result::Result<(), Error> {
99+
for Aarch64Register { id, value } in vcpu_config.cpu_config.regs.iter() {
100+
self.fd
101+
.set_one_reg(*id, *value)
102+
.map_err(|err| Error::ApplyCpuTemplate(ArchError::SetOneReg(*id, err)))?;
103+
}
104+
self.additional_register_ids = vcpu_config.cpu_config.register_ids();
105+
100106
crate::arch::aarch64::regs::setup_boot_regs(
101107
&self.fd,
102108
self.index,
@@ -108,12 +114,6 @@ impl KvmVcpu {
108114
self.mpidr =
109115
crate::arch::aarch64::regs::read_mpidr(&self.fd).map_err(Error::ConfigureRegisters)?;
110116

111-
vcpu_config
112-
.cpu_config
113-
.apply(&self.fd)
114-
.map_err(Error::ApplyCpuTemplate)?;
115-
self.additional_register_ids = vcpu_config.cpu_config.register_ids();
116-
117117
Ok(())
118118
}
119119

0 commit comments

Comments
 (0)