x86_64: fix mem size edge case with --mem=3328

When the RAM size is specified to be exactly 3328 MiB (4096 - 768),
there is no memory after the gap; however, the arch_memory_regions code
was adding a zero-sized region to the list of guest memory areas to be
mapped.

This would result in a mmap syscall failure at startup:

  [ERROR:src/main.rs:1590] The architecture failed to build the vm:
  failed to set up guest memory: failed to map guest memory: mmap system
  call failed: Invalid argument (os error 22)

Fix the off-by-one error when checking whether the address of the end of
guest memory is within 4 GB so that the > 4GB branch is not taken with
mem=3328.

BUG=chromium:1129547
TEST=crosvm run --mem=3328 vm_kernel
TEST=cargo test -p x86_64

Change-Id: I66cd66c98d690b42b2e1d97312528bb0d4830e76
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2417004
Reviewed-by: Ram Muthiah <rammuthiah@google.com>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
Daniel Verkamp 2020-09-17 15:15:02 -07:00 committed by Commit Bot
parent c76c2dae56
commit b3bafe023f

View file

@ -299,7 +299,7 @@ fn arch_memory_regions(size: u64, has_bios: bool) -> Vec<(GuestAddress, u64)> {
let end_32bit_gap_start = GuestAddress(END_ADDR_BEFORE_32BITS);
let mut regions = Vec::new();
if mem_end < end_32bit_gap_start {
if mem_end <= end_32bit_gap_start {
regions.push((GuestAddress(0), size));
if has_bios {
regions.push((GuestAddress(BIOS_START), BIOS_LEN as u64));
@ -877,4 +877,24 @@ mod tests {
assert_eq!(BIOS_LEN as u64, regions[1].1);
assert_eq!(GuestAddress(1u64 << 32), regions[2].0);
}
#[test]
fn regions_eq_4gb_nobios() {
// Test with size = 3328, which is exactly 4 GiB minus the size of the gap (768 MiB).
let regions = arch_memory_regions(3328 << 20, /* has_bios */ false);
assert_eq!(1, regions.len());
assert_eq!(GuestAddress(0), regions[0].0);
assert_eq!(3328 << 20, regions[0].1);
}
#[test]
fn regions_eq_4gb_bios() {
// Test with size = 3328, which is exactly 4 GiB minus the size of the gap (768 MiB).
let regions = arch_memory_regions(3328 << 20, /* has_bios */ true);
assert_eq!(2, regions.len());
assert_eq!(GuestAddress(0), regions[0].0);
assert_eq!(3328 << 20, regions[0].1);
assert_eq!(GuestAddress(BIOS_START), regions[1].0);
assert_eq!(BIOS_LEN as u64, regions[1].1);
}
}