Skip to content

Commit 1ad2900

Browse files
authored
Merge branch 'firecracker-microvm:main' into main
2 parents 38fff7a + ac42726 commit 1ad2900

12 files changed

Lines changed: 216 additions & 361 deletions

File tree

.buildkite/pipeline_perf.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
REVISION_B = os.environ.get("REVISION_B")
109109
REVISION_A_ARTIFACTS = os.environ.get("REVISION_A_ARTIFACTS")
110110
REVISION_B_ARTIFACTS = os.environ.get("REVISION_B_ARTIFACTS")
111+
A_B_TEST_MAX_ITERATIONS = 4
111112

112113
# Either both are specified or neither. Only doing either is a bug. If you want to
113114
# run performance tests _on_ a specific commit, specify neither and put your commit
@@ -125,21 +126,11 @@
125126
action="append",
126127
)
127128

128-
retry = {}
129-
if REVISION_A:
130-
# Enable automatic retry and disable manual retries to suppress spurious issues.
131-
retry["automatic"] = [
132-
{"exit_status": -1, "limit": 1},
133-
{"exit_status": 1, "limit": 1},
134-
]
135-
retry["manual"] = False
136-
137129
pipeline = BKPipeline(
138130
# Boost priority from 1 to 2 so these jobs are preferred by ag=1 agents
139131
priority=2,
140132
# use ag=1 instances to make sure no two performance tests are scheduled on the same instance
141133
agents={"ag": 1},
142-
retry=retry,
143134
# Heavy post-failure dumps (full snapshot + chroot copy) are useful
144135
# for triaging performance flakes that are hard to reproduce locally.
145136
# Cheap dumps are always on; this flag turns the heavy block on.
@@ -163,7 +154,7 @@
163154
artifacts = []
164155
if REVISION_A:
165156
devtool_opts += " --ab"
166-
test_script_opts = f'{ab_opts} run --binaries-a build/{REVISION_A}/ --binaries-b build/{REVISION_B} --pytest-opts "{test_selector}"'
157+
test_script_opts = f'{ab_opts} run --binaries-a build/{REVISION_A}/ --binaries-b build/{REVISION_B} --max-iterations={A_B_TEST_MAX_ITERATIONS} --pytest-opts "{test_selector}"'
167158
if REVISION_A_ARTIFACTS:
168159
artifacts.append(REVISION_A_ARTIFACTS)
169160
artifacts.append(REVISION_B_ARTIFACTS)

src/vmm/src/devices/virtio/mem/device.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,10 @@ impl VirtioMem {
539539
self.config.plugged_size -= usize_to_u64(self.nb_blocks_to_len(plugged_before));
540540
self.config.plugged_size += usize_to_u64(self.nb_blocks_to_len(plugged_after));
541541

542+
// Update kvm slots before doing any discards to prevent guest from re-faulting just
543+
// discarded memory.
544+
self.update_kvm_slots(range)?;
545+
542546
// If unplugging, discard the range
543547
if !plug {
544548
self.guest_memory()
@@ -550,8 +554,7 @@ impl VirtioMem {
550554
error!("virtio-mem: Failed to discard memory range: {}", err);
551555
});
552556
}
553-
554-
self.update_kvm_slots(range)
557+
Ok(())
555558
}
556559

557560
/// Updates the requested size of the virtio-mem device.

src/vmm/src/devices/virtio/net/device.rs

Lines changed: 51 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use crate::devices::{DeviceError, report_net_event_fail};
3939
use crate::dumbo::pdu::arp::ETH_IPV4_FRAME_LEN;
4040
use crate::dumbo::pdu::ethernet::{EthernetFrame, PAYLOAD_OFFSET};
4141
use crate::impl_device_type;
42-
use crate::logger::{IncMetric, METRICS, error};
42+
use crate::logger::{IncMetric, METRICS, error, warn};
4343
use crate::mmds::data_store::Mmds;
4444
use crate::mmds::ns::MmdsNetworkStack;
4545
use crate::rate_limiter::{BucketUpdate, RateLimiter, TokenType};
@@ -1032,24 +1032,12 @@ impl VirtioDevice for Net {
10321032
}
10331033

10341034
fn write_config(&mut self, offset: u64, data: &[u8]) {
1035-
let config_space_bytes = self.config_space.as_mut_slice();
1036-
let start = usize::try_from(offset).ok();
1037-
let end = start.and_then(|s| s.checked_add(data.len()));
1038-
// Only the guest_mac field (bytes 0..size_of::<MacAddr>()) is writable by the guest.
1039-
// All other fields (status, max_virtqueue_pairs, mtu) are read-only device fields.
1040-
let Some(dst) = start
1041-
.zip(end)
1042-
.filter(|&(_, end)| end <= std::mem::size_of::<MacAddr>())
1043-
.and_then(|(start, end)| config_space_bytes.get_mut(start..end))
1044-
else {
1045-
error!("Failed to write config space");
1046-
self.metrics.cfg_fails.inc();
1047-
return;
1048-
};
1049-
1050-
dst.copy_from_slice(data);
1051-
self.guest_mac = Some(self.config_space.guest_mac);
1052-
self.metrics.mac_address_updates.inc();
1035+
self.metrics.cfg_fails.inc();
1036+
warn!(
1037+
"virtio-net: guest driver attempted to write device config (offset={:#x}, len={:#x})",
1038+
offset,
1039+
data.len()
1040+
);
10531041
}
10541042

10551043
fn activate(
@@ -1295,42 +1283,52 @@ pub mod tests {
12951283
}
12961284

12971285
#[test]
1298-
fn test_virtio_device_rewrite_config() {
1286+
fn test_virtio_device_config_space_is_read_only() {
12991287
let mut net = default_net();
1300-
set_mac(&mut net, MacAddr::from_str("11:22:33:44:55:66").unwrap());
1301-
1302-
let new_config: [u8; MAC_ADDR_LEN as usize] = [0x66, 0x55, 0x44, 0x33, 0x22, 0x11];
1303-
net.write_config(0, &new_config);
1304-
let mut new_config_read = [0u8; MAC_ADDR_LEN as usize];
1305-
net.read_config(0, &mut new_config_read);
1306-
assert_eq!(new_config, new_config_read);
1307-
1308-
// Check that the guest MAC was updated.
1309-
let expected_guest_mac = MacAddr::from_bytes_unchecked(&new_config);
1310-
assert_eq!(expected_guest_mac, net.guest_mac.unwrap());
1311-
assert_eq!(net.metrics.mac_address_updates.count(), 1);
1312-
1313-
// Partial write (this is how the kernel sets a new mac address) - byte by byte.
1314-
let new_config = [0x11, 0x22, 0x33, 0x44, 0x55, 0x66];
1315-
for i in 0..new_config.len() {
1316-
net.write_config(i as u64, &new_config[i..=i]);
1288+
let initial_mac = MacAddr::from_str("11:22:33:44:55:66").unwrap();
1289+
set_mac(&mut net, initial_mac);
1290+
1291+
let initial_bytes: [u8; MAC_ADDR_LEN as usize] = [0x11, 0x22, 0x33, 0x44, 0x55, 0x66];
1292+
1293+
// Sanity check: the configured MAC is what the guest reads back.
1294+
let mut config_read = [0u8; MAC_ADDR_LEN as usize];
1295+
net.read_config(0, &mut config_read);
1296+
assert_eq!(config_read, initial_bytes);
1297+
assert_eq!(net.guest_mac.unwrap(), initial_mac);
1298+
1299+
// A 6-byte write to offset 0 must be rejected and leave both the
1300+
// config space bytes and the device's stored guest_mac unchanged.
1301+
let attempted_bytes: [u8; MAC_ADDR_LEN as usize] = [0x66, 0x55, 0x44, 0x33, 0x22, 0x11];
1302+
let cfg_fails_before = net.metrics.cfg_fails.count();
1303+
net.write_config(0, &attempted_bytes);
1304+
net.read_config(0, &mut config_read);
1305+
assert_eq!(config_read, initial_bytes);
1306+
assert_eq!(net.guest_mac.unwrap(), initial_mac);
1307+
assert_eq!(net.metrics.cfg_fails.count(), cfg_fails_before + 1);
1308+
1309+
// Single-byte writes covering the MAC region must also be rejected
1310+
// without changing state.
1311+
let cfg_fails_before = net.metrics.cfg_fails.count();
1312+
for i in 0..attempted_bytes.len() {
1313+
net.write_config(i as u64, &attempted_bytes[i..=i]);
13171314
}
1318-
net.read_config(0, &mut new_config_read);
1319-
assert_eq!(new_config, new_config_read);
1320-
1321-
// Invalid write.
1322-
net.write_config(5, &new_config);
1323-
// Verify old config was untouched.
1324-
new_config_read = [0u8; MAC_ADDR_LEN as usize];
1325-
net.read_config(0, &mut new_config_read);
1326-
assert_eq!(new_config, new_config_read);
1327-
1328-
// Large offset that may cause an overflow.
1329-
net.write_config(u64::MAX, &new_config);
1330-
// Verify old config was untouched.
1331-
new_config_read = [0u8; MAC_ADDR_LEN as usize];
1332-
net.read_config(0, &mut new_config_read);
1333-
assert_eq!(new_config, new_config_read);
1315+
net.read_config(0, &mut config_read);
1316+
assert_eq!(config_read, initial_bytes);
1317+
assert_eq!(net.guest_mac.unwrap(), initial_mac);
1318+
assert_eq!(
1319+
net.metrics.cfg_fails.count(),
1320+
cfg_fails_before + attempted_bytes.len() as u64
1321+
);
1322+
1323+
// Out-of-range and overflowing offsets must be rejected without
1324+
// changing state.
1325+
let cfg_fails_before = net.metrics.cfg_fails.count();
1326+
net.write_config(5, &attempted_bytes);
1327+
net.write_config(u64::MAX, &attempted_bytes);
1328+
net.read_config(0, &mut config_read);
1329+
assert_eq!(config_read, initial_bytes);
1330+
assert_eq!(net.guest_mac.unwrap(), initial_mac);
1331+
assert_eq!(net.metrics.cfg_fails.count(), cfg_fails_before + 2);
13341332
}
13351333

13361334
#[test]

src/vmm/src/devices/virtio/net/metrics.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,13 @@
1212
//! "net_eth0": {
1313
//! "activate_fails": "SharedIncMetric",
1414
//! "cfg_fails": "SharedIncMetric",
15-
//! "mac_address_updates": "SharedIncMetric",
1615
//! "no_rx_avail_buffer": "SharedIncMetric",
1716
//! "no_tx_avail_buffer": "SharedIncMetric",
1817
//! ...
1918
//! }
2019
//! "net_eth1": {
2120
//! "activate_fails": "SharedIncMetric",
2221
//! "cfg_fails": "SharedIncMetric",
23-
//! "mac_address_updates": "SharedIncMetric",
2422
//! "no_rx_avail_buffer": "SharedIncMetric",
2523
//! "no_tx_avail_buffer": "SharedIncMetric",
2624
//! ...
@@ -29,15 +27,13 @@
2927
//! "net_iface_id": {
3028
//! "activate_fails": "SharedIncMetric",
3129
//! "cfg_fails": "SharedIncMetric",
32-
//! "mac_address_updates": "SharedIncMetric",
3330
//! "no_rx_avail_buffer": "SharedIncMetric",
3431
//! "no_tx_avail_buffer": "SharedIncMetric",
3532
//! ...
3633
//! }
3734
//! "net": {
3835
//! "activate_fails": "SharedIncMetric",
3936
//! "cfg_fails": "SharedIncMetric",
40-
//! "mac_address_updates": "SharedIncMetric",
4137
//! "no_rx_avail_buffer": "SharedIncMetric",
4238
//! "no_tx_avail_buffer": "SharedIncMetric",
4339
//! ...
@@ -149,8 +145,6 @@ pub struct NetDeviceMetrics {
149145
pub activate_fails: SharedIncMetric,
150146
/// Number of times when interacting with the space config of a network device failed.
151147
pub cfg_fails: SharedIncMetric,
152-
/// Number of times the mac address was updated through the config space.
153-
pub mac_address_updates: SharedIncMetric,
154148
/// No available buffer for the net device rx queue.
155149
pub no_rx_avail_buffer: SharedIncMetric,
156150
/// No available buffer for the net device tx queue.
@@ -218,8 +212,6 @@ impl NetDeviceMetrics {
218212
pub fn aggregate(&mut self, other: &Self) {
219213
self.activate_fails.add(other.activate_fails.fetch_diff());
220214
self.cfg_fails.add(other.cfg_fails.fetch_diff());
221-
self.mac_address_updates
222-
.add(other.mac_address_updates.fetch_diff());
223215
self.no_rx_avail_buffer
224216
.add(other.no_rx_avail_buffer.fetch_diff());
225217
self.no_tx_avail_buffer

src/vmm/src/gdb/target.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
use std::cfg_select;
45
use std::collections::HashMap;
56
use std::sync::mpsc::{Receiver, RecvError};
67
use std::sync::{Arc, Mutex, PoisonError};
@@ -19,14 +20,16 @@ use gdbstub::target::ext::breakpoints::{
1920
};
2021
use gdbstub::target::ext::thread_extra_info::{ThreadExtraInfo, ThreadExtraInfoOps};
2122
use gdbstub::target::{Target, TargetError, TargetResult};
22-
#[cfg(target_arch = "aarch64")]
23-
use gdbstub_arch::aarch64::AArch64 as GdbArch;
24-
#[cfg(target_arch = "aarch64")]
25-
use gdbstub_arch::aarch64::reg::AArch64CoreRegs as CoreRegs;
26-
#[cfg(target_arch = "x86_64")]
27-
use gdbstub_arch::x86::X86_64_SSE as GdbArch;
28-
#[cfg(target_arch = "x86_64")]
29-
use gdbstub_arch::x86::reg::X86_64CoreRegs as CoreRegs;
23+
cfg_select! {
24+
target_arch = "aarch64" => {
25+
use gdbstub_arch::aarch64::AArch64 as GdbArch;
26+
use gdbstub_arch::aarch64::reg::AArch64CoreRegs as CoreRegs;
27+
}
28+
target_arch = "x86_64" => {
29+
use gdbstub_arch::x86::X86_64_SSE as GdbArch;
30+
use gdbstub_arch::x86::reg::X86_64CoreRegs as CoreRegs;
31+
}
32+
}
3033
use vm_memory::{Bytes, GuestAddress, GuestMemoryError};
3134

3235
use super::arch;

tests/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ compare boottime of microVMs between Firecracker binaries compiled from the
242242
```sh
243243
tools/devtool -y build --rev main --release
244244
tools/devtool -y build --rev HEAD --release
245-
tools/devtool -y test --no-build --ab -- run build/main build/HEAD --pytest-opts integration_tests/performance/test_boottime.py::test_boottime
245+
tools/devtool -y test --no-build --ab -- run --binaries-a build/main --binaries-b build/HEAD --pytest-opts integration_tests/performance/test_boottime.py::test_boottime
246246
```
247247

248248
To download custom artifacts use

tests/conftest.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -287,20 +287,6 @@ def bin_vmclock_path(test_fc_session_root_path):
287287
yield vmclock_helper_bin_path
288288

289289

290-
@pytest.fixture(scope="session")
291-
def change_net_config_space_bin(test_fc_session_root_path):
292-
"""Build a binary that changes the MMIO config space."""
293-
change_net_config_space_bin = os.path.join(
294-
test_fc_session_root_path, "change_net_config_space"
295-
)
296-
build_tools.gcc_compile(
297-
"host_tools/change_net_config_space.c",
298-
change_net_config_space_bin,
299-
extra_flags="-static",
300-
)
301-
yield change_net_config_space_bin
302-
303-
304290
@pytest.fixture(scope="session")
305291
def devmem_bin(test_fc_session_root_path):
306292
"""Build a minimal /dev/mem read/write tool."""

tests/host_tools/change_net_config_space.c

Lines changed: 0 additions & 88 deletions
This file was deleted.

tests/host_tools/fcmetrics.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ def validate_fc_metrics(metrics):
102102
net_metrics = [
103103
"activate_fails",
104104
"cfg_fails",
105-
"mac_address_updates",
106105
"no_rx_avail_buffer",
107106
"no_tx_avail_buffer",
108107
"event_fails",

0 commit comments

Comments
 (0)