Skip to content

Commit a678d39

Browse files
committed
refactor the shared/encrypted bitmaps to be partition-wide
1 parent 40aff86 commit a678d39

File tree

3 files changed

+202
-121
lines changed

3 files changed

+202
-121
lines changed

openhcl/underhill_mem/src/init.rs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use crate::HardwareIsolatedMemoryProtector;
77
use crate::MemoryAcceptor;
88
use crate::mapping::GuestMemoryMapping;
9+
use crate::mapping::GuestValidMemory;
910
use anyhow::Context;
1011
use futures::future::try_join_all;
1112
use guestmem::GuestMemory;
@@ -207,12 +208,19 @@ pub async fn init(params: &Init<'_>) -> anyhow::Result<MemoryMappings> {
207208
// Do not register this mapping with the kernel. It will not be safe for
208209
// use with syscalls that expect virtual addresses to be in
209210
// kernel-registered RAM.
211+
212+
tracing::debug!("Building valid encrypted memory view");
213+
let valid_encrypted_memory = Arc::new({
214+
let _span = tracing::info_span!("create encrypted memory bitmap").entered();
215+
GuestValidMemory::new(params.mem_layout, true)?
216+
});
217+
210218
tracing::debug!("Building VTL0 memory map");
211219
let vtl0_mapping = Arc::new({
212220
let _span = tracing::info_span!("map_vtl0_memory").entered();
213221
GuestMemoryMapping::builder(0)
214222
.dma_base_address(None) // prohibit direct DMA attempts until TDISP is supported
215-
.use_bitmap(Some(true))
223+
.use_partition_valid_memory(Some(valid_encrypted_memory.clone()))
216224
.build(&gpa_fd, params.mem_layout)
217225
.context("failed to map vtl0 memory")?
218226
});
@@ -280,26 +288,33 @@ pub async fn init(params: &Init<'_>) -> anyhow::Result<MemoryMappings> {
280288
// confused about shared memory, and our current use of kernel-mode
281289
// guest memory access is limited to low-perf paths where we can use
282290
// bounce buffering.
291+
283292
tracing::debug!("Building shared memory map");
293+
294+
let valid_shared_memory = Arc::new({
295+
let _span = tracing::info_span!("create shared memory bitmap").entered();
296+
GuestValidMemory::new(params.complete_memory_layout, false)?
297+
});
298+
299+
// Update the shared mapping bitmap for pages used by the shared
300+
// visibility pool to be marked as shared, since by default pages are
301+
// marked as no-access in the bitmap.
302+
tracing::debug!("Updating shared mapping bitmaps");
303+
for range in params.shared_pool {
304+
valid_shared_memory.update_valid(range.range, true);
305+
}
306+
284307
let shared_mapping = Arc::new({
285308
let _span = tracing::info_span!("map_shared_memory").entered();
286309
GuestMemoryMapping::builder(shared_offset)
287310
.shared(true)
288-
.use_bitmap(Some(false))
311+
.use_partition_valid_memory(Some(valid_shared_memory.clone()))
289312
.ignore_registration_failure(params.boot_init.is_none())
290313
.dma_base_address(Some(dma_base_address))
291314
.build(&gpa_fd, params.complete_memory_layout)
292315
.context("failed to map shared memory")?
293316
});
294317

295-
// Update the shared mapping bitmap for pages used by the shared
296-
// visibility pool to be marked as shared, since by default pages are
297-
// marked as no-access in the bitmap.
298-
tracing::debug!("Updating shared mapping bitmaps");
299-
for range in params.shared_pool {
300-
shared_mapping.update_bitmap(range.range, true);
301-
}
302-
303318
tracing::debug!("Creating VTL0 guest memory");
304319
let vtl0_gm = GuestMemory::new_multi_region(
305320
"vtl0",
@@ -308,6 +323,7 @@ pub async fn init(params: &Init<'_>) -> anyhow::Result<MemoryMappings> {
308323
)
309324
.context("failed to make vtl0 guest memory")?;
310325

326+
tracing::debug!("Creating VTL1 guest memory");
311327
let vtl1_gm = if params.maximum_vtl >= Vtl::Vtl1 {
312328
// TODO CVM GUEST VSM: This should not just use the vtl0_gm. This
313329
// could also be further tightened -- whether or not VTL 1 is
@@ -349,7 +365,8 @@ pub async fn init(params: &Init<'_>) -> anyhow::Result<MemoryMappings> {
349365
let private_vtl0_memory = GuestMemory::new("trusted", vtl0_mapping.clone());
350366

351367
let protector = Arc::new(HardwareIsolatedMemoryProtector::new(
352-
shared_mapping.clone(),
368+
valid_encrypted_memory.clone(),
369+
valid_shared_memory.clone(),
353370
vtl0_mapping.clone(),
354371
params.mem_layout.clone(),
355372
acceptor.as_ref().unwrap().clone(),

openhcl/underhill_mem/src/lib.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use hvdef::hypercall::AcceptMemoryType;
3434
use hvdef::hypercall::HostVisibilityType;
3535
use hvdef::hypercall::HvInputVtl;
3636
use mapping::GuestMemoryMapping;
37+
use mapping::GuestValidMemory;
3738
use memory_range::MemoryRange;
3839
use parking_lot::Mutex;
3940
use registrar::RegisterMemory;
@@ -382,7 +383,8 @@ struct HypercallOverlay {
382383
}
383384

384385
struct HardwareIsolatedMemoryProtectorInner {
385-
shared: Arc<GuestMemoryMapping>,
386+
valid_encrypted: Arc<GuestValidMemory>,
387+
valid_shared: Arc<GuestValidMemory>,
386388
encrypted: Arc<GuestMemoryMapping>,
387389
default_vtl_permissions: DefaultVtlPermissions,
388390
vtl1_protections_enabled: bool,
@@ -394,14 +396,16 @@ impl HardwareIsolatedMemoryProtector {
394396
/// `shared` provides the mapping for shared memory. `vtl0` provides the
395397
/// mapping for encrypted memory.
396398
pub fn new(
397-
shared: Arc<GuestMemoryMapping>,
399+
valid_encrypted: Arc<GuestValidMemory>,
400+
valid_shared: Arc<GuestValidMemory>,
398401
encrypted: Arc<GuestMemoryMapping>,
399402
layout: MemoryLayout,
400403
acceptor: Arc<MemoryAcceptor>,
401404
) -> Self {
402405
Self {
403406
inner: Mutex::new(HardwareIsolatedMemoryProtectorInner {
404-
shared,
407+
valid_encrypted,
408+
valid_shared,
405409
encrypted,
406410
// Grant only VTL 0 all permissions. This will be altered
407411
// later by VTL 1 enablement and by VTL 1 itself.
@@ -504,7 +508,7 @@ impl ProtectIsolatedMemory for HardwareIsolatedMemoryProtector {
504508
let gpns = gpns
505509
.iter()
506510
.copied()
507-
.filter(|&gpn| inner.shared.check_bitmap(gpn) != shared)
511+
.filter(|&gpn| inner.valid_shared.check_valid(gpn) != shared)
508512
.collect::<Vec<_>>();
509513

510514
tracing::debug!(
@@ -524,12 +528,12 @@ impl ProtectIsolatedMemory for HardwareIsolatedMemoryProtector {
524528

525529
// Prevent accesses via the wrong address.
526530
let clear_bitmap = if shared {
527-
&inner.encrypted
531+
&inner.valid_encrypted
528532
} else {
529-
&inner.shared
533+
&inner.valid_shared
530534
};
531535
for &range in &ranges {
532-
clear_bitmap.update_bitmap(range, false);
536+
clear_bitmap.update_valid(range, false);
533537
}
534538

535539
// There may be other threads concurrently accessing these pages. We
@@ -605,7 +609,7 @@ impl ProtectIsolatedMemory for HardwareIsolatedMemoryProtector {
605609
.expect("previous gpns was already checked");
606610

607611
for &range in &rollback_ranges {
608-
clear_bitmap.update_bitmap(range, true);
612+
clear_bitmap.update_valid(range, true);
609613
}
610614

611615
// Figure out the index of the gpn that failed, in the
@@ -637,12 +641,12 @@ impl ProtectIsolatedMemory for HardwareIsolatedMemoryProtector {
637641

638642
// Allow accesses via the correct address.
639643
let set_bitmap = if shared {
640-
&inner.shared
644+
&inner.valid_shared
641645
} else {
642-
&inner.encrypted
646+
&inner.valid_encrypted
643647
};
644648
for &range in &ranges {
645-
set_bitmap.update_bitmap(range, true);
649+
set_bitmap.update_valid(range, true);
646650
}
647651

648652
if !shared {
@@ -695,7 +699,7 @@ impl ProtectIsolatedMemory for HardwareIsolatedMemoryProtector {
695699

696700
// Set GPN sharing status in output.
697701
for (gpn, host_vis) in gpns.iter().zip(host_visibility.iter_mut()) {
698-
*host_vis = if inner.shared.check_bitmap(*gpn) {
702+
*host_vis = if inner.valid_shared.check_valid(*gpn) {
699703
HostVisibilityType::SHARED
700704
} else {
701705
HostVisibilityType::PRIVATE
@@ -739,7 +743,7 @@ impl ProtectIsolatedMemory for HardwareIsolatedMemoryProtector {
739743
// find all accepted memory. When lazy acceptance exists,
740744
// this should track all pages that have been accepted and
741745
// should be used instead.
742-
if !inner.encrypted.check_bitmap(gpn) {
746+
if !inner.valid_encrypted.check_valid(gpn) {
743747
if page_count > 0 {
744748
let end_address = protect_start + (page_count * PAGE_SIZE as u64);
745749
ranges.push(MemoryRange::new(protect_start..end_address));
@@ -793,7 +797,7 @@ impl ProtectIsolatedMemory for HardwareIsolatedMemoryProtector {
793797
let inner = self.inner.lock();
794798

795799
// Protections cannot be applied to a host-visible page
796-
if gpns.iter().any(|&gpn| inner.shared.check_bitmap(gpn)) {
800+
if gpns.iter().any(|&gpn| inner.valid_shared.check_valid(gpn)) {
797801
return Err((HvError::OperationDenied, 0));
798802
}
799803

0 commit comments

Comments
 (0)