Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify microvm builder code and make uffd test failures easier to debug #4991

Merged
merged 5 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ and this project adheres to
- [#4916](https://github.com/firecracker-microvm/firecracker/pull/4916): Fixed
`IovDeque` implementation to work with any host page size. This fixes
virtio-net device on non 4K host kernels.
- [#4991](https://github.com/firecracker-microvm/firecracker/pull/4991): Fixed
`mem_size_mib` and `track_dirty_pages` being mandatory for all
`PATCH /machine-config` requests. Now, they can be omitted which leaves these
parts of the machine configuration unchanged.

## [1.10.1]

Expand Down
2 changes: 1 addition & 1 deletion src/cpu-template-helper/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ fn run(cli: Cli) -> Result<(), HelperError> {
let (vmm, vm_resources) = utils::build_microvm_from_config(config, template)?;

let cpu_template = vm_resources
.vm_config
.machine_config
.cpu_template
.get_cpu_template()?
.into_owned();
Expand Down
1 change: 1 addition & 0 deletions src/firecracker/examples/uffd/fault_all_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ fn main() {
let (stream, _) = listener.accept().expect("Cannot listen on UDS socket");

let mut runtime = Runtime::new(stream, file);
runtime.install_panic_hook();
runtime.run(|uffd_handler: &mut UffdHandler| {
// Read an event from the userfaultfd.
let event = uffd_handler
Expand Down
37 changes: 37 additions & 0 deletions src/firecracker/examples/uffd/uffd_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,43 @@ impl Runtime {
}
}

fn peer_process_credentials(&self) -> libc::ucred {
let mut creds: libc::ucred = libc::ucred {
pid: 0,
gid: 0,
uid: 0,
};
let mut creds_size = size_of::<libc::ucred>() as u32;
let ret = unsafe {
libc::getsockopt(
self.stream.as_raw_fd(),
libc::SOL_SOCKET,
libc::SO_PEERCRED,
&mut creds as *mut _ as *mut _,
&mut creds_size as *mut libc::socklen_t,
)
};
if ret != 0 {
panic!("Failed to get peer process credentials");
}
creds
}

pub fn install_panic_hook(&self) {
let peer_creds = self.peer_process_credentials();

let default_panic_hook = std::panic::take_hook();
std::panic::set_hook(Box::new(move |panic_info| {
let r = unsafe { libc::kill(peer_creds.pid, libc::SIGKILL) };

if r != 0 {
eprintln!("Failed to kill Firecracker process from panic hook");
}

default_panic_hook(panic_info);
}));
}

/// Polls the `UnixStream` and UFFD fds in a loop.
/// When stream is polled, new uffd is retrieved.
/// When uffd is polled, page fault is handled by
Expand Down
1 change: 1 addition & 0 deletions src/firecracker/examples/uffd/valid_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ fn main() {
let (stream, _) = listener.accept().expect("Cannot listen on UDS socket");

let mut runtime = Runtime::new(stream, file);
runtime.install_panic_hook();
runtime.run(|uffd_handler: &mut UffdHandler| {
// Read an event from the userfaultfd.
let event = uffd_handler
Expand Down
4 changes: 2 additions & 2 deletions src/firecracker/src/api_server/parsed_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ impl ParsedRequest {
info!("The request was executed successfully. Status code: 204 No Content.");
Response::new(Version::Http11, StatusCode::NoContent)
}
VmmData::MachineConfiguration(vm_config) => {
Self::success_response_with_data(vm_config)
VmmData::MachineConfiguration(machine_config) => {
Self::success_response_with_data(machine_config)
}
VmmData::MmdsValue(value) => Self::success_response_with_mmds_value(value),
VmmData::BalloonConfig(balloon_config) => {
Expand Down
16 changes: 9 additions & 7 deletions src/firecracker/src/api_server/request/machine_configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ pub(crate) fn parse_put_machine_config(body: &Body) -> Result<ParsedRequest, Req
let config_update = MachineConfigUpdate::from(config);

// Construct the `ParsedRequest` object.
let mut parsed_req = ParsedRequest::new_sync(VmmAction::UpdateVmConfiguration(config_update));
let mut parsed_req =
ParsedRequest::new_sync(VmmAction::UpdateMachineConfiguration(config_update));
// If `cpu_template` was present, set the deprecation message in `parsing_info`.
if let Some(msg) = deprecation_message {
parsed_req.parsing_info().append_deprecation_message(msg);
Expand Down Expand Up @@ -60,7 +61,8 @@ pub(crate) fn parse_patch_machine_config(body: &Body) -> Result<ParsedRequest, R
}

// Construct the `ParsedRequest` object.
let mut parsed_req = ParsedRequest::new_sync(VmmAction::UpdateVmConfiguration(config_update));
let mut parsed_req =
ParsedRequest::new_sync(VmmAction::UpdateMachineConfiguration(config_update));
// If `cpu_template` was present, set the deprecation message in `parsing_info`.
if let Some(msg) = deprecation_message {
parsed_req.parsing_info().append_deprecation_message(msg);
Expand Down Expand Up @@ -124,7 +126,7 @@ mod tests {
};
assert_eq!(
vmm_action_from_request(parse_put_machine_config(&Body::new(body)).unwrap()),
VmmAction::UpdateVmConfiguration(expected_config)
VmmAction::UpdateMachineConfiguration(expected_config)
);
}

Expand All @@ -143,7 +145,7 @@ mod tests {
};
assert_eq!(
vmm_action_from_request(parse_put_machine_config(&Body::new(body)).unwrap()),
VmmAction::UpdateVmConfiguration(expected_config)
VmmAction::UpdateMachineConfiguration(expected_config)
);

let body = r#"{
Expand All @@ -162,7 +164,7 @@ mod tests {
};
assert_eq!(
vmm_action_from_request(parse_put_machine_config(&Body::new(body)).unwrap()),
VmmAction::UpdateVmConfiguration(expected_config)
VmmAction::UpdateMachineConfiguration(expected_config)
);

// 4. Test that applying a CPU template is successful on x86_64 while on aarch64, it is not.
Expand All @@ -185,7 +187,7 @@ mod tests {
};
assert_eq!(
vmm_action_from_request(parse_put_machine_config(&Body::new(body)).unwrap()),
VmmAction::UpdateVmConfiguration(expected_config)
VmmAction::UpdateMachineConfiguration(expected_config)
);
}
#[cfg(target_arch = "aarch64")]
Expand All @@ -210,7 +212,7 @@ mod tests {
};
assert_eq!(
vmm_action_from_request(parse_put_machine_config(&Body::new(body)).unwrap()),
VmmAction::UpdateVmConfiguration(expected_config)
VmmAction::UpdateMachineConfiguration(expected_config)
);

// 6. Test nonsense values for huge page size
Expand Down
6 changes: 3 additions & 3 deletions src/vmm/benches/memory_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
use vm_memory::GuestMemory;
use vmm::resources::VmResources;
use vmm::vmm_config::machine_config::{HugePageConfig, VmConfig};
use vmm::vmm_config::machine_config::{HugePageConfig, MachineConfig};

fn bench_single_page_fault(c: &mut Criterion, configuration: VmResources) {
c.bench_function("page_fault", |b| {
Expand Down Expand Up @@ -33,7 +33,7 @@ pub fn bench_4k_page_fault(c: &mut Criterion) {
bench_single_page_fault(
c,
VmResources {
vm_config: VmConfig {
machine_config: MachineConfig {
vcpu_count: 1,
mem_size_mib: 2,
..Default::default()
Expand All @@ -47,7 +47,7 @@ pub fn bench_2m_page_fault(c: &mut Criterion) {
bench_single_page_fault(
c,
VmResources {
vm_config: VmConfig {
machine_config: MachineConfig {
vcpu_count: 1,
mem_size_mib: 2,
huge_pages: HugePageConfig::Hugetlbfs2M,
Expand Down
35 changes: 19 additions & 16 deletions src/vmm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
use crate::utils::u64_to_usize;
use crate::vmm_config::boot_source::BootConfig;
use crate::vmm_config::instance_info::InstanceInfo;
use crate::vmm_config::machine_config::{VmConfig, VmConfigError};
use crate::vmm_config::machine_config::{MachineConfig, MachineConfigError};

Check warning on line 70 in src/vmm/src/builder.rs

View check run for this annotation

Codecov / codecov/patch

src/vmm/src/builder.rs#L70

Added line #L70 was not covered by tests
use crate::vstate::memory::{GuestAddress, GuestMemory, GuestMemoryMmap};
use crate::vstate::vcpu::{Vcpu, VcpuConfig, VcpuError};
use crate::vstate::vm::Vm;
Expand Down Expand Up @@ -124,7 +124,7 @@
/// Cannot restore microvm state: {0}
RestoreMicrovmState(MicrovmStateError),
/// Cannot set vm resources: {0}
SetVmResources(VmConfigError),
SetVmResources(MachineConfigError),

Check warning on line 127 in src/vmm/src/builder.rs

View check run for this annotation

Codecov / codecov/patch

src/vmm/src/builder.rs#L127

Added line #L127 was not covered by tests
/// Cannot create the entropy device: {0}
CreateEntropyDevice(crate::devices::virtio::rng::EntropyError),
/// Failed to allocate guest resource: {0}
Expand Down Expand Up @@ -274,15 +274,18 @@
#[allow(unused_mut)]
let mut boot_cmdline = boot_config.cmdline.clone();

let cpu_template = vm_resources.vm_config.cpu_template.get_cpu_template()?;
let cpu_template = vm_resources
.machine_config
.cpu_template
.get_cpu_template()?;

let (mut vmm, mut vcpus) = create_vmm_and_vcpus(
instance_info,
event_manager,
guest_memory,
None,
vm_resources.vm_config.track_dirty_pages,
vm_resources.vm_config.vcpu_count,
vm_resources.machine_config.track_dirty_pages,
vm_resources.machine_config.vcpu_count,
cpu_template.kvm_capabilities.clone(),
)?;

Expand Down Expand Up @@ -338,7 +341,7 @@
configure_system_for_boot(
&mut vmm,
vcpus.as_mut(),
&vm_resources.vm_config,
&vm_resources.machine_config,
&cpu_template,
entry_addr,
&initrd,
Expand All @@ -348,7 +351,7 @@
let vmm = Arc::new(Mutex::new(vmm));

#[cfg(feature = "gdb")]
if let Some(gdb_socket_path) = &vm_resources.vm_config.gdb_socket_path {
if let Some(gdb_socket_path) = &vm_resources.machine_config.gdb_socket_path {
gdb::gdb_thread(vmm.clone(), vcpu_fds, gdb_rx, entry_addr, gdb_socket_path)
.map_err(GdbServer)?;
} else {
Expand Down Expand Up @@ -429,7 +432,7 @@
/// Failed to restore microVM state: {0}
RestoreState(#[from] crate::vstate::vm::RestoreStateError),
/// Failed to update microVM configuration: {0}
VmUpdateConfig(#[from] VmConfigError),
VmUpdateConfig(#[from] MachineConfigError),
/// Failed to restore MMIO device: {0}
RestoreMmioDevice(#[from] MicrovmStateError),
/// Failed to emulate MMIO serial: {0}
Expand Down Expand Up @@ -469,10 +472,10 @@
let (mut vmm, mut vcpus) = create_vmm_and_vcpus(
instance_info,
event_manager,
guest_memory.clone(),
guest_memory,
uffd,
vm_resources.vm_config.track_dirty_pages,
vm_resources.vm_config.vcpu_count,
vm_resources.machine_config.track_dirty_pages,
vm_resources.machine_config.vcpu_count,
microvm_state.vm_state.kvm_cap_modifiers.clone(),
)?;

Expand Down Expand Up @@ -514,7 +517,7 @@

// Restore devices states.
let mmio_ctor_args = MMIODevManagerConstructorArgs {
mem: &guest_memory,
mem: &vmm.guest_memory,
vm: vmm.vm.fd(),
event_manager,
resource_allocator: &mut vmm.resource_allocator,
Expand All @@ -529,7 +532,7 @@

{
let acpi_ctor_args = ACPIDeviceManagerConstructorArgs {
mem: &guest_memory,
mem: &vmm.guest_memory,
resource_allocator: &mut vmm.resource_allocator,
vm: vmm.vm.fd(),
};
Expand Down Expand Up @@ -750,7 +753,7 @@
pub fn configure_system_for_boot(
vmm: &mut Vmm,
vcpus: &mut [Vcpu],
vm_config: &VmConfig,
machine_config: &MachineConfig,
cpu_template: &CustomCpuTemplate,
entry_addr: GuestAddress,
initrd: &Option<InitrdConfig>,
Expand Down Expand Up @@ -793,8 +796,8 @@
let cpu_config = CpuConfiguration::apply_template(cpu_config, cpu_template)?;

let vcpu_config = VcpuConfig {
vcpu_count: vm_config.vcpu_count,
smt: vm_config.smt,
vcpu_count: machine_config.vcpu_count,
smt: machine_config.smt,
cpu_config,
};

Expand Down
18 changes: 9 additions & 9 deletions src/vmm/src/persist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
use crate::utils::u64_to_usize;
use crate::vmm_config::boot_source::BootSourceConfig;
use crate::vmm_config::instance_info::InstanceInfo;
use crate::vmm_config::machine_config::{HugePageConfig, MachineConfigUpdate, VmConfigError};
use crate::vmm_config::machine_config::{HugePageConfig, MachineConfigError, MachineConfigUpdate};
use crate::vmm_config::snapshot::{
CreateSnapshotParams, LoadSnapshotParams, MemBackendType, SnapshotType,
};
Expand Down Expand Up @@ -61,11 +61,11 @@
impl From<&VmResources> for VmInfo {
fn from(value: &VmResources) -> Self {
Self {
mem_size_mib: value.vm_config.mem_size_mib as u64,
smt: value.vm_config.smt,
cpu_template: StaticCpuTemplate::from(&value.vm_config.cpu_template),
mem_size_mib: value.machine_config.mem_size_mib as u64,
smt: value.machine_config.smt,
cpu_template: StaticCpuTemplate::from(&value.machine_config.cpu_template),
boot_source: value.boot_source.config.clone(),
huge_pages: value.vm_config.huge_pages,
huge_pages: value.machine_config.huge_pages,
}
}
}
Expand Down Expand Up @@ -422,11 +422,11 @@
.vcpu_states
.len()
.try_into()
.map_err(|_| VmConfigError::InvalidVcpuCount)
.map_err(|_| MachineConfigError::InvalidVcpuCount)
.map_err(BuildMicrovmFromSnapshotError::VmUpdateConfig)?;

vm_resources
.update_vm_config(&MachineConfigUpdate {
.update_machine_config(&MachineConfigUpdate {
vcpu_count: Some(vcpu_count),
mem_size_mib: Some(u64_to_usize(microvm_state.vm_info.mem_size_mib)),
smt: Some(microvm_state.vm_info.smt),
Expand All @@ -450,7 +450,7 @@
mem_backend_path,
mem_state,
track_dirty_pages,
vm_resources.vm_config.huge_pages,
vm_resources.machine_config.huge_pages,
)
.map_err(RestoreFromSnapshotGuestMemoryError::File)?,
None,
Expand All @@ -462,7 +462,7 @@
// We enable the UFFD_FEATURE_EVENT_REMOVE feature only if a balloon device
// is present in the microVM state.
microvm_state.device_states.balloon_device.is_some(),
vm_resources.vm_config.huge_pages,
vm_resources.machine_config.huge_pages,

Check warning on line 465 in src/vmm/src/persist.rs

View check run for this annotation

Codecov / codecov/patch

src/vmm/src/persist.rs#L465

Added line #L465 was not covered by tests
)
.map_err(RestoreFromSnapshotGuestMemoryError::Uffd)?,
};
Expand Down
Loading
Loading