Skip to content

Commit 8f503e3

Browse files
committed
WIP: kani proofs
Signed-off-by: Babis Chalios <[email protected]>
1 parent d1fda34 commit 8f503e3

File tree

4 files changed

+34
-40
lines changed

4 files changed

+34
-40
lines changed

src/vmm/src/arch/x86_64/layout.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
1010
use crate::utils::mib_to_bytes;
1111

12+
/// Maximum physical memory address space.
13+
///
14+
/// Typically, x86_64 architecture supports up to 48 bits of physical addresses.
15+
/// This space includes the MMIO addresses.
16+
pub const MAX_PHYSICAL_ADDRESS_SPACE: usize = 1usize << 48;
17+
1218
/// Initial stack for the boot CPU.
1319
pub const BOOT_STACK_POINTER: u64 = 0x8ff0;
1420

src/vmm/src/arch/x86_64/mod.rs

Lines changed: 25 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ pub mod generated;
3434
use std::fs::File;
3535

3636
use layout::{
37-
CMDLINE_START, FIRST_ADDR_PAST_32BITS, FIRST_ADDR_PAST_64BITS_MMIO, MMIO32_MEM_SIZE,
38-
MMIO32_MEM_START, MMIO64_MEM_SIZE, MMIO64_MEM_START,
37+
CMDLINE_START, FIRST_ADDR_PAST_32BITS, FIRST_ADDR_PAST_64BITS_MMIO, MAX_PHYSICAL_ADDRESS_SPACE,
38+
MMIO32_MEM_SIZE, MMIO32_MEM_START, MMIO64_MEM_SIZE, MMIO64_MEM_START,
3939
};
4040
use linux_loader::configurator::linux::LinuxBootConfigurator;
4141
use linux_loader::configurator::pvh::PvhBootConfigurator;
@@ -101,22 +101,25 @@ pub enum ConfigurationError {
101101

102102
/// Returns a Vec of the valid memory addresses.
103103
/// These should be used to configure the GuestMemoryMmap structure for the platform.
104-
/// For x86_64 all addresses are valid from the start of the kernel except a
105-
/// carve out at the end of 32bit address space.
106-
pub fn arch_memory_regions(offset: usize, size: usize) -> Vec<(GuestAddress, usize)> {
104+
/// For x86_64 all addresses are valid from the start of the kernel except an 1GB
105+
/// carve out at the end of 32bit address space and a second 256GB one at the 256GB limit.
106+
pub fn arch_memory_regions(size: usize) -> Vec<(GuestAddress, usize)> {
107107
// If we get here with size == 0 something has seriously gone wrong. Firecracker should never
108108
// try to allocate guest memory of size 0
109109
assert!(size > 0, "Attempt to allocate guest memory of length 0");
110+
// The resulting address space must fit in 48 bits.
110111
assert!(
111-
offset.checked_add(size).is_some(),
112-
"Attempt to allocate guest memory such that the address space would wrap around"
112+
size <= MAX_PHYSICAL_ADDRESS_SPACE
113+
- u64_to_usize(MMIO32_MEM_SIZE)
114+
- u64_to_usize(MMIO64_MEM_SIZE),
115+
"Memory size would result in an address space that exceeds 48 bits."
113116
);
114117

115118
let mut regions = vec![];
116119

117120
if let Some((start_past_32bit_gap, remaining_past_32bit_gap)) = arch_memory_regions_with_gap(
118121
&mut regions,
119-
offset,
122+
0,
120123
size,
121124
u64_to_usize(MMIO32_MEM_START),
122125
u64_to_usize(MMIO32_MEM_SIZE),
@@ -473,24 +476,30 @@ pub fn load_kernel(
473476
mod verification {
474477
use crate::arch::arch_memory_regions;
475478
use crate::arch::x86_64::layout::{
476-
FIRST_ADDR_PAST_32BITS, FIRST_ADDR_PAST_64BITS_MMIO, MMIO32_MEM_START, MMIO64_MEM_START,
479+
FIRST_ADDR_PAST_32BITS, FIRST_ADDR_PAST_64BITS_MMIO, MAX_PHYSICAL_ADDRESS_SPACE,
480+
MMIO32_MEM_SIZE, MMIO32_MEM_START, MMIO64_MEM_SIZE, MMIO64_MEM_START,
477481
};
482+
use crate::utils::usize_to_u64;
478483

479484
#[kani::proof]
480485
#[kani::unwind(4)]
481486
fn verify_arch_memory_regions() {
482-
let offset: u64 = kani::any::<u64>();
483487
let len: u64 = kani::any::<u64>();
484488

485489
kani::assume(len > 0);
486-
kani::assume(offset.checked_add(len).is_some());
490+
kani::assume(
491+
len <= usize_to_u64(MAX_PHYSICAL_ADDRESS_SPACE) - MMIO32_MEM_SIZE - MMIO64_MEM_SIZE,
492+
);
487493

488-
let regions = arch_memory_regions(offset as usize, len as usize);
494+
let regions = arch_memory_regions(len as usize);
489495

490496
// There are two MMIO gaps, so we can get either 1, 2 or 3 regions
491497
assert!(regions.len() <= 3);
492498
assert!(regions.len() >= 1);
493499

500+
// The first address is always 0
501+
assert_eq!(regions[0].0.0, 0);
502+
494503
// The total length of all regions is what we requested
495504
assert_eq!(
496505
regions.iter().map(|&(_, len)| len).sum::<usize>(),
@@ -507,23 +516,15 @@ mod verification {
507516
|| start.0 + len as u64 <= MMIO64_MEM_START))
508517
);
509518

510-
// All regions start after our specified offset
511-
assert!(regions.iter().all(|&(start, _)| start.0 >= offset as u64));
512-
513519
// All regions have non-zero length
514520
assert!(regions.iter().all(|&(_, len)| len > 0));
515521

516522
// If there's at least two regions, they perfectly snuggle up to one of the two MMIO gaps
517523
if regions.len() >= 2 {
518524
kani::cover!();
519525

520-
if offset < MMIO32_MEM_START {
521-
assert_eq!(regions[0].0.0 + regions[0].1 as u64, MMIO32_MEM_START);
522-
assert_eq!(regions[1].0.0, FIRST_ADDR_PAST_32BITS);
523-
} else {
524-
assert_eq!(regions[0].0.0 + regions[0].1 as u64, MMIO64_MEM_START);
525-
assert_eq!(regions[1].0.0, FIRST_ADDR_PAST_64BITS_MMIO);
526-
}
526+
assert_eq!(regions[0].0.0 + regions[0].1 as u64, MMIO32_MEM_START);
527+
assert_eq!(regions[1].0.0, FIRST_ADDR_PAST_64BITS_MMIO);
527528
}
528529

529530
// If there are three regions, the last two perfectly snuggle up to the 64bit
@@ -548,34 +549,21 @@ mod tests {
548549

549550
#[test]
550551
fn regions_lt_4gb() {
551-
let regions = arch_memory_regions(0, 1usize << 29);
552+
let regions = arch_memory_regions(1usize << 29);
552553
assert_eq!(1, regions.len());
553554
assert_eq!(GuestAddress(0), regions[0].0);
554555
assert_eq!(1usize << 29, regions[0].1);
555-
556-
let regions = arch_memory_regions(1 << 28, 1 << 29);
557-
assert_eq!(1, regions.len());
558-
assert_eq!(regions[0], (GuestAddress(1 << 28), 1 << 29));
559556
}
560557

561558
#[test]
562559
fn regions_gt_4gb() {
563560
const MEMORY_SIZE: usize = (1 << 32) + 0x8000;
564561

565-
let regions = arch_memory_regions(0, MEMORY_SIZE);
562+
let regions = arch_memory_regions(MEMORY_SIZE);
566563
assert_eq!(2, regions.len());
567564
assert_eq!(GuestAddress(0), regions[0].0);
568565
assert_eq!(GuestAddress(1u64 << 32), regions[1].0);
569566

570-
let regions = arch_memory_regions(1 << 31, MEMORY_SIZE);
571-
assert_eq!(2, regions.len());
572-
assert_eq!(
573-
regions[0],
574-
(
575-
GuestAddress(1 << 31),
576-
u64_to_usize(MMIO32_MEM_START) - (1 << 31)
577-
)
578-
);
579567
assert_eq!(
580568
regions[1],
581569
(

src/vmm/src/resources.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ impl VmResources {
474474
// a single way of backing guest memory for vhost-user and non-vhost-user cases,
475475
// that would not be worth the effort.
476476
let regions =
477-
crate::arch::arch_memory_regions(0, mib_to_bytes(self.machine_config.mem_size_mib));
477+
crate::arch::arch_memory_regions(mib_to_bytes(self.machine_config.mem_size_mib));
478478
if vhost_user_device_used {
479479
memory::memfd_backed(
480480
regions.as_ref(),

src/vmm/src/test_utils/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ pub fn multi_region_mem_raw(regions: &[(GuestAddress, usize)]) -> Vec<GuestRegio
5858
/// Creates a [`GuestMemoryMmap`] of the given size with the contained regions laid out in
5959
/// accordance with the requirements of the architecture on which the tests are being run.
6060
pub fn arch_mem(mem_size_bytes: usize) -> GuestMemoryMmap {
61-
multi_region_mem(&crate::arch::arch_memory_regions(0, mem_size_bytes))
61+
multi_region_mem(&crate::arch::arch_memory_regions(mem_size_bytes))
6262
}
6363

6464
pub fn arch_mem_raw(mem_size_bytes: usize) -> Vec<GuestRegionMmap> {
65-
multi_region_mem_raw(&crate::arch::arch_memory_regions(0, mem_size_bytes))
65+
multi_region_mem_raw(&crate::arch::arch_memory_regions(mem_size_bytes))
6666
}
6767

6868
pub fn create_vmm(

0 commit comments

Comments
 (0)