-
Notifications
You must be signed in to change notification settings - Fork 195
feat(aarch64): add WHP backend for ARM64 Windows #1638
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?
Changes from 6 commits
2ba9a0b
9b59799
1d3a299
5cb75f1
af8dafc
05d5350
c468267
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 |
|---|---|---|
|
|
@@ -17,7 +17,9 @@ limitations under the License. | |
| // TODO(aarch64): implement arch-specific HyperlightVm methods | ||
|
|
||
| use std::sync::Arc; | ||
| use std::sync::atomic::{AtomicBool, AtomicU8, AtomicU64}; | ||
| use std::sync::atomic::AtomicU8; | ||
| #[cfg(target_os = "linux")] | ||
| use std::sync::atomic::{AtomicBool, AtomicU64}; | ||
|
|
||
| use super::{ | ||
| AccessPageTableError, CreateHyperlightVmError, DispatchGuestCallError, HyperlightVm, | ||
|
|
@@ -29,12 +31,17 @@ use crate::hypervisor::hyperlight_vm::get_guest_log_filter; | |
| use crate::hypervisor::regs::{CommonFpu, CommonRegisters, CommonSpecialRegisters}; | ||
| #[cfg(kvm)] | ||
| use crate::hypervisor::virtual_machine::kvm::KvmVm; | ||
| #[cfg(kvm)] | ||
| #[cfg(target_os = "windows")] | ||
| use crate::hypervisor::virtual_machine::whp::WhpVm; | ||
| #[cfg(any(kvm, mshv3, target_os = "windows"))] | ||
| use crate::hypervisor::virtual_machine::{HypervisorType, VmError}; | ||
| use crate::hypervisor::virtual_machine::{ | ||
| RegisterError, ResetVcpuError, VirtualMachine, get_available_hypervisor, | ||
| }; | ||
| #[cfg(target_os = "linux")] | ||
| use crate::hypervisor::{InterruptHandleImpl, LinuxInterruptHandle}; | ||
| #[cfg(target_os = "windows")] | ||
| use crate::hypervisor::{InterruptHandleImpl, PartitionState, WindowsInterruptHandle}; | ||
| use crate::mem::mgr::{SandboxMemoryManager, SnapshotSharedMemory}; | ||
| use crate::mem::shared_mem::{GuestSharedMemory, HostSharedMemory}; | ||
| use crate::sandbox::SandboxConfiguration; | ||
|
|
@@ -54,7 +61,7 @@ impl HyperlightVm { | |
| next_action: NextAction, | ||
| rsp_gva: u64, | ||
| page_size: usize, | ||
| config: &SandboxConfiguration, | ||
| #[cfg_attr(target_os = "windows", allow(unused_variables))] config: &SandboxConfiguration, | ||
| #[cfg(gdb)] _gdb_conn: Option<DebugCommChannel<DebugResponse, DebugMsg>>, | ||
| #[cfg(crashdump)] _rt_cfg: SandboxRuntimeConfig, | ||
| #[cfg(feature = "mem_profile")] _trace_info: MemTraceInfo, | ||
|
|
@@ -64,13 +71,19 @@ impl HyperlightVm { | |
| let vm: VmType = match get_available_hypervisor() { | ||
| #[cfg(kvm)] | ||
| Some(HypervisorType::Kvm) => Box::new(KvmVm::new().map_err(VmError::CreateVm)?), | ||
| // TODO: mshv support | ||
| #[cfg(mshv3)] | ||
| Some(HypervisorType::Mshv) => return Err(CreateHyperlightVmError::NoHypervisorFound), | ||
| Some(HypervisorType::Mshv) => { | ||
| // MSHV aarch64 VirtualMachine impl not yet available on this branch | ||
| return Err(CreateHyperlightVmError::NoHypervisorFound); | ||
| } | ||
| #[cfg(target_os = "windows")] | ||
| Some(HypervisorType::Whp) => Box::new(WhpVm::new().map_err(VmError::CreateVm)?), | ||
| None => return Err(CreateHyperlightVmError::NoHypervisorFound), | ||
| }; | ||
| vm.set_sregs(&CommonSpecialRegisters::defaults(root_pt_addr)) | ||
| .map_err(VmError::Register)?; | ||
|
|
||
| #[cfg(target_os = "linux")] | ||
| let interrupt_handle: Arc<dyn InterruptHandleImpl> = Arc::new(LinuxInterruptHandle { | ||
| state: AtomicU8::new(0), | ||
| tid: AtomicU64::new(unsafe { libc::pthread_self() as u64 }), | ||
|
|
@@ -79,6 +92,15 @@ impl HyperlightVm { | |
| dropped: AtomicBool::new(false), | ||
| }); | ||
|
|
||
| #[cfg(target_os = "windows")] | ||
| let interrupt_handle: Arc<dyn InterruptHandleImpl> = Arc::new(WindowsInterruptHandle { | ||
|
Member
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. Just a heads up that there is a big refactor/simplification to the interrupt handle machinery in #1674 that you may want to take a look at. |
||
| state: AtomicU8::new(0), | ||
| partition_state: std::sync::RwLock::new(PartitionState { | ||
| handle: vm.partition_handle(), | ||
| dropped: false, | ||
| }), | ||
| }); | ||
|
|
||
| let snapshot_slot = 0u32; | ||
| let scratch_slot = 1u32; | ||
| let vm_can_reset_vcpu = vm.can_reset_vcpu(); | ||
|
|
@@ -214,7 +236,7 @@ impl HyperlightVm { | |
| self.vm_can_reset_vcpu, | ||
| "No fallback path for vcpu reset on aarch64" | ||
| ); | ||
| self.vm.reset_vcpu()?; | ||
| self.interrupt_handle.reset_vcpu(self.vm.as_mut())?; | ||
|
Member
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. What's this change about? It seems like the wrong place for this. If it's related to the locking that happens in the interrupt handle: that's required because the interrupt handle can outlive the |
||
| self.apply_sregs(cr3, sregs)?; | ||
| Ok(()) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,6 +46,9 @@ use std::sync::atomic::{AtomicU8, Ordering}; | |
| #[cfg(any(kvm, mshv3))] | ||
| use std::time::Duration; | ||
|
|
||
| #[cfg(target_arch = "aarch64")] | ||
| use self::virtual_machine::{ResetVcpuError, VirtualMachine}; | ||
|
|
||
| /// A trait for platform-specific interrupt handle implementation details | ||
| pub(crate) trait InterruptHandleImpl: InterruptHandle { | ||
| /// Set the thread ID for the vcpu thread | ||
|
|
@@ -67,6 +70,12 @@ pub(crate) trait InterruptHandleImpl: InterruptHandle { | |
| /// Clear the cancellation request flag | ||
| fn clear_cancel(&self); | ||
|
|
||
| /// Reset the vCPU while honoring platform lifecycle synchronization. | ||
| #[cfg(target_arch = "aarch64")] | ||
|
Member
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. As mentioned above, this seems like the wrong place for this. |
||
| fn reset_vcpu(&self, vm: &mut dyn VirtualMachine) -> Result<(), ResetVcpuError> { | ||
| vm.reset_vcpu() | ||
| } | ||
|
|
||
| /// Check if debug interrupt was requested (always returns false when gdb feature is disabled) | ||
| fn is_debug_interrupted(&self) -> bool; | ||
|
|
||
|
|
@@ -347,6 +356,20 @@ impl InterruptHandleImpl for WindowsInterruptHandle { | |
| self.state.fetch_and(!Self::RUNNING_BIT, Ordering::Release); | ||
| } | ||
|
|
||
| #[cfg(target_arch = "aarch64")] | ||
| fn reset_vcpu(&self, vm: &mut dyn VirtualMachine) -> Result<(), ResetVcpuError> { | ||
| let guard = self | ||
| .partition_state | ||
| .write() | ||
| .map_err(|e| ResetVcpuError::Unknown(e.to_string()))?; | ||
| if guard.dropped { | ||
| return Err(ResetVcpuError::Unknown( | ||
| "cannot reset a dropped partition".to_string(), | ||
| )); | ||
| } | ||
| vm.reset_vcpu() | ||
| } | ||
|
|
||
| fn is_debug_interrupted(&self) -> bool { | ||
| #[cfg(gdb)] | ||
| { | ||
|
|
||
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.
This line looks like it's the same before/after?