-
Notifications
You must be signed in to change notification settings - Fork 190
Hypercall to let the VTL0 or VTL1 to retrieve its VMPCK so that it can communicate with the PSP #3408
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
base: main
Are you sure you want to change the base?
Hypercall to let the VTL0 or VTL1 to retrieve its VMPCK so that it can communicate with the PSP #3408
Changes from all commits
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 | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1346,6 +1346,7 @@ pub struct Hcl { | |||||||||||||||||
| isolation: IsolationType, | ||||||||||||||||||
| snp_register_bitmap: [u8; 64], | ||||||||||||||||||
| sidecar: Option<SidecarClient>, | ||||||||||||||||||
|
||||||||||||||||||
| sidecar: Option<SidecarClient>, | |
| sidecar: Option<SidecarClient>, | |
| #[cfg(target_arch = "x86_64")] |
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.
Do we need to store this? It looks like we're only checking it once in the constructor?
Copilot
AI
Apr 30, 2026
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.
Hcl::new is now only defined under #[cfg(guest_arch = "x86_64")], but there are call sites (e.g. the #[cfg(not(guest_arch = "x86_64"))] path in virt_mshv_vtl) that still expect an Hcl::new(isolation, sidecar) constructor. Add a complementary #[cfg(not(guest_arch = "x86_64"))] constructor (or refactor to a single signature) so non-x86_64 guest builds continue to compile.
| #[cfg(guest_arch = "x86_64")] // xtask-fmt allow-target-arch cpu-intrinsic | |
| pub fn new( | |
| isolation: IsolationType, | |
| sidecar: Option<SidecarClient>, | |
| pub fn new( | |
| isolation: IsolationType, | |
| sidecar: Option<SidecarClient>, | |
| #[cfg(guest_arch = "x86_64")] // xtask-fmt allow-target-arch cpu-intrinsic |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
|
|
||
| [package] | ||
| name = "openhcl_cpuid_features" | ||
| edition.workspace = true | ||
| rust-version.workspace = true | ||
|
|
||
| [target.'cfg(target_arch = "x86_64")'.dependencies] | ||
| hvdef.workspace = true | ||
| x86defs.workspace = true | ||
| safe_intrinsics.workspace = true | ||
|
|
||
| [lints] | ||
| workspace = true |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
|
|
||
| //! Shared CPUID feature detection for OpenHCL components. | ||
|
|
||
| // xtask-fmt allow-target-arch cpu-intrinsic | ||
| #![cfg(target_arch = "x86_64")] | ||
|
|
||
| use hvdef::HvEnlightenmentInformation; | ||
| use x86defs::cpuid::VersionAndFeaturesEcx; | ||
|
|
||
| /// Cached CPUID feature detection results. | ||
| #[derive(Clone, Copy, Debug)] | ||
| pub struct CpuidFeatures { | ||
| enlightenment_info: HvEnlightenmentInformation, | ||
| version_features: VersionAndFeaturesEcx, | ||
| } | ||
|
|
||
| impl CpuidFeatures { | ||
| /// Queries host CPUID and builds a snapshot of relevant feature leaves. | ||
| pub fn new() -> Self { | ||
| let result = | ||
| safe_intrinsics::cpuid(hvdef::HV_CPUID_FUNCTION_MS_HV_ENLIGHTENMENT_INFORMATION, 0); | ||
| let enlightenment_info = HvEnlightenmentInformation::from_cpuid([ | ||
| result.eax, result.ebx, result.ecx, result.edx, | ||
| ]); | ||
|
|
||
| let result = safe_intrinsics::cpuid(x86defs::cpuid::CpuidFunction::VersionAndFeatures.0, 0); | ||
| let version_features = VersionAndFeaturesEcx::from(result.ecx); | ||
|
|
||
| Self { | ||
| enlightenment_info, | ||
| version_features, | ||
| } | ||
| } | ||
|
|
||
| /// Returns whether Hyper-V recommends MMIO access hypercalls. | ||
| pub fn use_hypercall_for_mmio_access(&self) -> bool { | ||
| self.enlightenment_info.use_hypercall_for_mmio_access() | ||
| } | ||
|
|
||
| /// Returns whether x2APIC is supported by the host CPU. | ||
| pub fn x2_apic_supported(&self) -> bool { | ||
| self.version_features.x2_apic() | ||
| } | ||
|
|
||
| /// Returns whether lower VTL guest request interception is supported. | ||
| pub fn supports_lower_vtl_guest_request(&self) -> bool { | ||
| self.enlightenment_info.lower_vtl_guest_request_support() | ||
| } | ||
|
|
||
| /// Returns whether restore partition time on resume is supported. | ||
| pub fn supports_restore_partition_time(&self) -> bool { | ||
| self.enlightenment_info.restore_time_on_resume() | ||
| } | ||
| } | ||
|
|
||
| impl Default for CpuidFeatures { | ||
| fn default() -> Self { | ||
| Self::new() | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1591,21 +1591,15 @@ async fn new_underhill_vm( | |
| let uevent_listener = | ||
| Arc::new(UeventListener::new(tp.driver(0)).context("failed to start uevent listener")?); | ||
|
|
||
| let use_mmio_hypercalls = dps.general.always_relay_host_mmio; | ||
| // TODO: Centralize cpuid based feature determination. | ||
| // Initialize CPUID features once at worker startup. | ||
| #[cfg(guest_arch = "x86_64")] // xtask-fmt allow-target-arch cpu-intrinsic | ||
| let cpuid_features = openhcl_cpuid_features::CpuidFeatures::new(); | ||
|
|
||
| #[cfg(guest_arch = "x86_64")] | ||
| let use_mmio_hypercalls = use_mmio_hypercalls | ||
| || hardware_isolated && { | ||
| let result = | ||
| safe_intrinsics::cpuid(hvdef::HV_CPUID_FUNCTION_MS_HV_ENLIGHTENMENT_INFORMATION, 0); | ||
| hvdef::HvEnlightenmentInformation::from( | ||
| result.eax as u128 | ||
| | (result.ebx as u128) << 32 | ||
| | (result.ecx as u128) << 64 | ||
| | (result.edx as u128) << 96, | ||
| ) | ||
| .use_hypercall_for_mmio_access() | ||
| }; | ||
| let use_mmio_hypercalls = dps.general.always_relay_host_mmio | ||
| || (hardware_isolated && cpuid_features.use_hypercall_for_mmio_access()); | ||
| #[cfg(not(guest_arch = "x86_64"))] | ||
| let use_mmio_hypercalls = dps.general.always_relay_host_mmio; | ||
|
|
||
| let boot_info = runtime_params.parsed_openhcl_boot(); | ||
|
|
||
|
|
@@ -1713,21 +1707,14 @@ async fn new_underhill_vm( | |
| // boot rather than allowing the host to make that decision. This would | ||
| // just require Underhill setting the apicbase register on the VPs | ||
| // before start. | ||
| // | ||
| // TODO: centralize cpuid querying logic. | ||
|
Member
Author
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. This PR took the liberty to centralize the cpuid querying logic (as the PR also needed to make a cpuid call). If the general direction is right, I can try to converge other HCL cpuid calls into the cpuid crate in this PR or a subsequent PR. |
||
| #[cfg(guest_arch = "x86_64")] | ||
| let x2apic = if isolation.is_hardware_isolated() && !hide_isolation { | ||
| // For hardware CVMs, always enable x2apic support at boot. | ||
| vm_topology::processor::x86::X2ApicState::Enabled | ||
| } else if cpuid_features.x2_apic_supported() { | ||
| vm_topology::processor::x86::X2ApicState::Supported | ||
| } else { | ||
| let features = x86defs::cpuid::VersionAndFeaturesEcx::from( | ||
| safe_intrinsics::cpuid(x86defs::cpuid::CpuidFunction::VersionAndFeatures.0, 0).ecx, | ||
| ); | ||
| if features.x2_apic() { | ||
| vm_topology::processor::x86::X2ApicState::Supported | ||
| } else { | ||
| vm_topology::processor::x86::X2ApicState::Unsupported | ||
| } | ||
| vm_topology::processor::x86::X2ApicState::Unsupported | ||
| }; | ||
|
|
||
| #[cfg(guest_arch = "x86_64")] | ||
|
|
@@ -1871,6 +1858,8 @@ async fn new_underhill_vm( | |
| hide_isolation, | ||
| disable_proxy_redirect: env_cfg.disable_proxy_redirect, | ||
| disable_lower_vtl_timer_virt: env_cfg.disable_lower_vtl_timer_virt, | ||
| #[cfg(guest_arch = "x86_64")] // xtask-fmt allow-target-arch cpu-intrinsic | ||
| cpuid_features, | ||
| }; | ||
|
|
||
| let proto_partition = UhProtoPartition::new(params, |cpu| tp.driver(cpu).clone()) | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -1440,6 +1440,9 @@ pub struct UhPartitionNewParams<'a> { | |||||
| pub disable_proxy_redirect: bool, | ||||||
| /// Disable lower VTL timer virtualization. | ||||||
| pub disable_lower_vtl_timer_virt: bool, | ||||||
| /// Cached CPUID features queried once at worker startup. | ||||||
| #[cfg(guest_arch = "x86_64")] // xtask-fmt allow-target-arch cpu-intrinsic | ||||||
| pub cpuid_features: openhcl_cpuid_features::CpuidFeatures, | ||||||
| } | ||||||
|
|
||||||
| /// Parameters to [`UhProtoPartition::build`]. | ||||||
|
|
@@ -1610,6 +1613,9 @@ impl<'a> UhProtoPartition<'a> { | |||||
| // Try to open the sidecar device, if it is present. | ||||||
| let sidecar = sidecar_client::SidecarClient::new(driver).map_err(Error::Sidecar)?; | ||||||
|
|
||||||
| #[cfg(guest_arch = "x86_64")] // xtask-fmt allow-target-arch cpu-intrinsic | ||||||
| let hcl = Hcl::new(hcl_isolation, sidecar, params.cpuid_features).map_err(Error::Hcl)?; | ||||||
| #[cfg(not(guest_arch = "x86_64"))] // xtask-fmt allow-target-arch cpu-intrinsic | ||||||
| let hcl = Hcl::new(hcl_isolation, sidecar).map_err(Error::Hcl)?; | ||||||
|
||||||
| let hcl = Hcl::new(hcl_isolation, sidecar).map_err(Error::Hcl)?; | |
| let hcl = Hcl::new(hcl_isolation, sidecar, params.cpuid_features).map_err(Error::Hcl)?; |
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.
openhcl_cpuid_featuresis an x86_64-only crate (cfg(target_arch = "x86_64")). Adding it as an unconditional Linux dependency forhclcan cause non-x86_64 Linux builds to fail unless the code is fullycfg-gated or the crate provides non-x86 stubs. Consider moving this dependency under acfg(target_arch = "x86_64")target section (or otherwise ensuring non-x86 builds don’t pull in/use this crate).