x86_64: calculate CMOS memory values from mem map

The existing mem_below_4g/mem_above_4g calculations did not match the
actual layout used when populating guest memory.  Rather than
duplicating the logic in setup_io_bus to calculate the values reported
in CMOS, just reuse the arch_memory_regions function and count the bytes
in the regions below and above the 4G boundary.

Bug: 168740534
Bug: 168628037
Link: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2422129
TEST: Verify u-boot reports 4 GiB with crosvm --mem=4096

Change-Id: I32a70f19848595eaefd2e31c9f31a260d6ce4453
diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs
index b490274..bce5b91 100644
--- a/x86_64/src/lib.rs
+++ b/x86_64/src/lib.rs
@@ -707,9 +707,19 @@
 
         let mut io_bus = devices::Bus::new();
 
-        let mem_gap_start = END_ADDR_BEFORE_32BITS;
-        let mem_below_4g = std::cmp::min(mem_gap_start, mem_size);
-        let mem_above_4g = mem_size.saturating_sub(FIRST_ADDR_PAST_32BITS);
+        let mem_regions = arch_memory_regions(mem_size, false);
+
+        let mem_below_4g = mem_regions
+            .iter()
+            .filter(|r| r.0.offset() < FIRST_ADDR_PAST_32BITS)
+            .map(|r| r.1)
+            .sum();
+
+        let mem_above_4g = mem_regions
+            .iter()
+            .filter(|r| r.0.offset() >= FIRST_ADDR_PAST_32BITS)
+            .map(|r| r.1)
+            .sum();
 
         io_bus
             .insert(