-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for Hyper-V firmware execution #201
Changes from 1 commit
3dd317f
c82bd89
fcb7ec8
1cc4b8e
b760045
5832f34
b3580d8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -19,6 +19,44 @@ use crate::serial::SERIAL_PORT; | |||||||||||||||||
use crate::utils::MemoryRegion; | ||||||||||||||||||
use alloc::vec::Vec; | ||||||||||||||||||
|
||||||||||||||||||
fn check_ovmf_regions( | ||||||||||||||||||
flash_regions: &[MemoryRegion<PhysAddr>], | ||||||||||||||||||
kernel_region: &MemoryRegion<PhysAddr>, | ||||||||||||||||||
) { | ||||||||||||||||||
Comment on lines
+23
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Further to our email/call discussion about the name of 'flash' in SVSM, I wonder if this function and parameters should be renamed. I'm not sure what would be a good name for the region from 3GB-4GB. ROM region? System region?
Suggested change
|
||||||||||||||||||
let flash_range = { | ||||||||||||||||||
let one_gib = 1024 * 1024 * 1024usize; | ||||||||||||||||||
let start = PhysAddr::from(3 * one_gib); | ||||||||||||||||||
MemoryRegion::new(start, one_gib) | ||||||||||||||||||
}; | ||||||||||||||||||
|
||||||||||||||||||
// Sanity-check flash regions. | ||||||||||||||||||
for region in flash_regions.iter() { | ||||||||||||||||||
// Make sure that the regions are between 3GiB and 4GiB. | ||||||||||||||||||
if !region.overlap(&flash_range) { | ||||||||||||||||||
panic!("flash region in unexpected region"); | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
// Make sure that no regions overlap with the kernel. | ||||||||||||||||||
if region.overlap(kernel_region) { | ||||||||||||||||||
panic!("flash region overlaps with kernel"); | ||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
// Make sure that regions don't overlap. | ||||||||||||||||||
for (i, outer) in flash_regions.iter().enumerate() { | ||||||||||||||||||
for inner in flash_regions[..i].iter() { | ||||||||||||||||||
if outer.overlap(inner) { | ||||||||||||||||||
panic!("flash regions overlap"); | ||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
// Make sure that one regions ends at 4GiB. | ||||||||||||||||||
let one_region_ends_at_4gib = flash_regions | ||||||||||||||||||
.iter() | ||||||||||||||||||
.any(|region| region.end() == flash_range.end()); | ||||||||||||||||||
assert!(one_region_ends_at_4gib); | ||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
#[derive(Debug)] | ||||||||||||||||||
pub enum SvsmConfig<'a> { | ||||||||||||||||||
FirmwareConfig(FwCfg<'a>), | ||||||||||||||||||
|
@@ -93,12 +131,30 @@ impl<'a> SvsmConfig<'a> { | |||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
pub fn get_fw_regions(&self) -> Result<Vec<MemoryRegion<PhysAddr>>, SvsmError> { | ||||||||||||||||||
pub fn get_fw_regions( | ||||||||||||||||||
&self, | ||||||||||||||||||
kernel_region: &MemoryRegion<PhysAddr>, | ||||||||||||||||||
) -> Vec<MemoryRegion<PhysAddr>> { | ||||||||||||||||||
match self { | ||||||||||||||||||
SvsmConfig::FirmwareConfig(fw_cfg) => { | ||||||||||||||||||
Ok(fw_cfg.iter_flash_regions().collect::<Vec<_>>()) | ||||||||||||||||||
let flash_regions = fw_cfg.iter_flash_regions().collect::<Vec<_>>(); | ||||||||||||||||||
check_ovmf_regions(&flash_regions, kernel_region); | ||||||||||||||||||
flash_regions | ||||||||||||||||||
} | ||||||||||||||||||
SvsmConfig::IgvmConfig(igvm_params) => igvm_params.get_fw_regions(), | ||||||||||||||||||
SvsmConfig::IgvmConfig(igvm_params) => { | ||||||||||||||||||
let flash_regions = igvm_params.get_fw_regions(); | ||||||||||||||||||
if !igvm_params.fw_in_low_memory() { | ||||||||||||||||||
check_ovmf_regions(&flash_regions, kernel_region); | ||||||||||||||||||
} | ||||||||||||||||||
Comment on lines
+147
to
+149
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Renaming
Suggested change
|
||||||||||||||||||
flash_regions | ||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
pub fn fw_in_low_memory(&self) -> bool { | ||||||||||||||||||
match self { | ||||||||||||||||||
SvsmConfig::FirmwareConfig(_) => false, | ||||||||||||||||||
SvsmConfig::IgvmConfig(igvm_params) => igvm_params.fw_in_low_memory(), | ||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,6 @@ use crate::error::SvsmError::Firmware; | |
use crate::fw_meta::SevFWMetaData; | ||
use crate::mm::PAGE_SIZE; | ||
use crate::utils::MemoryRegion; | ||
use alloc::vec; | ||
use alloc::vec::Vec; | ||
|
||
use bootlib::igvm_params::{IgvmParamBlock, IgvmParamPage}; | ||
|
@@ -22,6 +21,8 @@ use igvm_defs::{IgvmEnvironmentInfo, MemoryMapEntryType, IGVM_VHS_MEMORY_MAP_ENT | |
|
||
const IGVM_MEMORY_ENTRIES_PER_PAGE: usize = PAGE_SIZE / size_of::<IGVM_VHS_MEMORY_MAP_ENTRY>(); | ||
|
||
const STAGE2_END_ADDR: usize = 0xA0000; | ||
|
||
#[derive(Clone, Debug)] | ||
#[repr(C, align(64))] | ||
pub struct IgvmMemoryMap { | ||
|
@@ -199,14 +200,26 @@ impl IgvmParams<'_> { | |
} | ||
} | ||
|
||
pub fn get_fw_regions(&self) -> Result<Vec<MemoryRegion<PhysAddr>>, SvsmError> { | ||
if !self.should_launch_fw() { | ||
Err(Firmware) | ||
} else { | ||
Ok(vec![MemoryRegion::new( | ||
PhysAddr::new(self.igvm_param_block.firmware.start as usize), | ||
self.igvm_param_block.firmware.size as usize, | ||
)]) | ||
pub fn get_fw_regions(&self) -> Vec<MemoryRegion<PhysAddr>> { | ||
assert!(self.should_launch_fw()); | ||
|
||
let mut regions = Vec::new(); | ||
|
||
if self.igvm_param_block.firmware.in_low_memory != 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could use |
||
// Add the stage 2 region to the firmware region list so | ||
// permissions can be granted to the guest VMPL for that range. | ||
regions.push(MemoryRegion::new(PhysAddr::new(0), STAGE2_END_ADDR)); | ||
} | ||
|
||
regions.push(MemoryRegion::new( | ||
PhysAddr::new(self.igvm_param_block.firmware.start as usize), | ||
self.igvm_param_block.firmware.size as usize, | ||
)); | ||
|
||
regions | ||
} | ||
|
||
pub fn fw_in_low_memory(&self) -> bool { | ||
self.igvm_param_block.firmware.in_low_memory != 0 | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if it makes more sense to invert this flag and name it something like
in_system_region
(see comment below regarding 'system')? This would then explain the change in behaviour when the firmware uses the ROM region. Or just rename it tooutside_system_region
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could; my intention here was that any parameter that is zero continues the existing behavior, and new behavior is only invoked by non-zero parameters. That means that the existing "FW lives in ROM range" idea would be associated with a zero parameter. There's no good reason that I can't invert that if we think it enhances clarity.