vmm: Preserve SEV-SNP IGVM load ordering

Preserve the original IGVM import order for KVM SNP launch updates.
The launch digest is order-sensitive, so only coalesce adjacent pages
that already share the same page type and size. MSHV continues to
sort by GPA for hypercall batching.

Signed-off-by: Kevin Hui <kevinhui@meta.com>
This commit is contained in:
Kevin Hui
2026-05-01 09:25:30 -07:00
committed by Rob Bradford
parent 982934fba0
commit 4a91b4a608

View File

@@ -697,6 +697,11 @@ pub fn load_igvm(
let area = parameter_areas let area = parameter_areas
.get_mut(parameter_area_index) .get_mut(parameter_area_index)
.expect("igvmfile should be valid"); .expect("igvmfile should be valid");
#[cfg(feature = "kvm")]
let page_count = match area {
ParameterAreaState::Allocated { max_size, .. } => *max_size / HV_PAGE_SIZE,
ParameterAreaState::Inserted => panic!("igvmfile is invalid, multiple insert"),
};
match area { match area {
ParameterAreaState::Allocated { data, max_size } => { ParameterAreaState::Allocated { data, max_size } => {
#[cfg(all( #[cfg(all(
@@ -732,11 +737,25 @@ pub fn load_igvm(
ParameterAreaState::Inserted => panic!("igvmfile is invalid, multiple insert"), ParameterAreaState::Inserted => panic!("igvmfile is invalid, multiple insert"),
} }
*area = ParameterAreaState::Inserted; *area = ParameterAreaState::Inserted;
gpas.push(GpaPages { match hypervisor_type {
gpa: *gpa, #[cfg(feature = "kvm")]
page_type: page_types.unmeasured, HypervisorType::Kvm => {
page_size: page_types.isolated_page_size_4kb, for page_index in 0..page_count {
}); gpas.push(GpaPages {
gpa: *gpa + page_index * HV_PAGE_SIZE,
page_type: page_types.unmeasured,
page_size: page_types.isolated_page_size_4kb,
});
}
}
_ => {
gpas.push(GpaPages {
gpa: *gpa,
page_type: page_types.unmeasured,
page_size: page_types.isolated_page_size_4kb,
});
}
}
} }
IgvmDirectiveHeader::ErrorRange { .. } => { IgvmDirectiveHeader::ErrorRange { .. } => {
todo!("Error Range not supported") todo!("Error Range not supported")
@@ -786,14 +805,24 @@ pub fn load_igvm(
let mut now = Instant::now(); let mut now = Instant::now();
// Sort the gpas to group them by the page type // KVM: preserve original IGVM ordering — the SNP launch digest is order-sensitive.
gpas.sort_by_key(|a| a.gpa); // MSHV: sort by GPA to group pages by type for fewer hypercalls.
match hypervisor_type {
#[cfg(feature = "kvm")]
HypervisorType::Kvm => {}
_ => gpas.sort_by_key(|a| a.gpa),
}
let gpas_grouped = gpas let gpas_grouped = gpas
.iter() .iter()
.fold(Vec::<Vec<GpaPages>>::new(), |mut acc, gpa| { .fold(Vec::<Vec<GpaPages>>::new(), |mut acc, gpa| {
if let Some(last_vec) = acc.last_mut() if let Some(last_vec) = acc.last_mut()
&& last_vec[0].page_type == gpa.page_type && last_vec[0].page_type == gpa.page_type
&& match hypervisor_type {
#[cfg(feature = "kvm")]
HypervisorType::Kvm => last_vec[0].page_size == gpa.page_size,
_ => true,
}
{ {
last_vec.push(*gpa); last_vec.push(*gpa);
return acc; return acc;
@@ -802,8 +831,7 @@ pub fn load_igvm(
acc acc
}); });
// Import the pages as a group(by page type) of PFNs to reduce the // Import pages as groups of PFNs to reduce hypercalls.
// hypercall.
for group in gpas_grouped.iter() { for group in gpas_grouped.iter() {
info!( info!(
"Importing {} page{}", "Importing {} page{}",