| 2427 | |
| 2428 | #[cfg(feature = "sev_snp")] |
| 2429 | fn gain_page_access(&self, gpa: u64, size: u32) -> vm::Result<()> { |
| 2430 | use mshv_ioctls::set_bits; |
| 2431 | const ONE_GB: usize = 1024 * 1024 * 1024; |
| 2432 | |
| 2433 | if !self.sev_snp_enabled { |
| 2434 | return Ok(()); |
| 2435 | } |
| 2436 | |
| 2437 | let start_gpfn: u64 = gpa >> PAGE_SHIFT; |
| 2438 | let end_gpfn: u64 = (gpa + size as u64 - 1) >> PAGE_SHIFT; |
| 2439 | |
| 2440 | // Enlarge the bitmap if the PFN is greater than the bitmap length |
| 2441 | if end_gpfn >= self.host_access_pages.load().as_ref().len() as u64 { |
| 2442 | self.host_access_pages.rcu(|bitmap| { |
| 2443 | let mut bm = bitmap.as_ref().clone(); |
| 2444 | bm.enlarge(ONE_GB); |
| 2445 | bm |
| 2446 | }); |
| 2447 | } |
| 2448 | |
| 2449 | let gpas: Vec<u64> = (start_gpfn..=end_gpfn) |
| 2450 | .filter(|x| { |
| 2451 | !self |
| 2452 | .host_access_pages |
| 2453 | .load() |
| 2454 | .as_ref() |
| 2455 | .is_bit_set(*x as usize) |
| 2456 | }) |
| 2457 | .map(|x| x << PAGE_SHIFT) |
| 2458 | .collect(); |
| 2459 | |
| 2460 | if !gpas.is_empty() { |
| 2461 | let mut gpa_list = vec_with_array_field::<mshv_modify_gpa_host_access, u64>(gpas.len()); |
| 2462 | gpa_list[0].page_count = gpas.len() as u64; |
| 2463 | gpa_list[0].flags = set_bits!( |
| 2464 | u8, |
| 2465 | MSHV_GPA_HOST_ACCESS_BIT_ACQUIRE, |
| 2466 | MSHV_GPA_HOST_ACCESS_BIT_READABLE, |
| 2467 | MSHV_GPA_HOST_ACCESS_BIT_WRITABLE |
| 2468 | ); |
| 2469 | |
| 2470 | // SAFETY: gpa_list initialized with gpas.len() and now it is being turned into |
| 2471 | // gpas_slice with gpas.len() again. It is guaranteed to be large enough to hold |
| 2472 | // everything from gpas. |
| 2473 | unsafe { |
| 2474 | let gpas_slice: &mut [u64] = gpa_list[0].guest_pfns.as_mut_slice(gpas.len()); |
| 2475 | gpas_slice.copy_from_slice(gpas.as_slice()); |
| 2476 | } |
| 2477 | |
| 2478 | self.fd |
| 2479 | .modify_gpa_host_access(&gpa_list[0]) |
| 2480 | .map_err(|e| vm::HypervisorVmError::ModifyGpaHostAccess(e.into()))?; |
| 2481 | |
| 2482 | for acquired_gpa in gpas { |
| 2483 | self.host_access_pages.rcu(|bitmap| { |
| 2484 | let bm = bitmap.clone(); |
| 2485 | bm.set_bit((acquired_gpa >> PAGE_SHIFT) as usize); |
| 2486 | bm |