Skip to content

Commit aa3f9e6

Browse files
committed
Revert "save - move probe logic to common emu crate"
This reverts commit 7e808dd.
1 parent 7e808dd commit aa3f9e6

File tree

11 files changed

+113
-284
lines changed

11 files changed

+113
-284
lines changed

openhcl/virt_mshv_vtl/src/processor/mod.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ use virt::StopVp;
7474
use virt::VpHaltReason;
7575
use virt::VpIndex;
7676
use virt::io::CpuIo;
77-
use virt_support_x86emu::emulate::EmulationPolicy;
7877
use vm_topology::processor::TargetVpInfo;
7978
use vmcore::vmtime::VmTimeAccess;
8079

@@ -1107,7 +1106,6 @@ impl<'a, T: Backing> UhProcessor<'a, T> {
11071106
interruption_pending: bool,
11081107
vtl: GuestVtl,
11091108
cache: T::EmulationCache,
1110-
policy: EmulationPolicy<'_>,
11111109
) -> Result<(), VpHaltReason<UhRunVpError>>
11121110
where
11131111
for<'b> UhEmulationState<'b, 'a, D, T>:
@@ -1121,8 +1119,7 @@ impl<'a, T: Backing> UhProcessor<'a, T> {
11211119
vtl,
11221120
cache,
11231121
};
1124-
virt_support_x86emu::emulate::emulate(&mut emulation_state, guest_memory, devices, policy)
1125-
.await
1122+
virt_support_x86emu::emulate::emulate(&mut emulation_state, guest_memory, devices).await
11261123
}
11271124

11281125
/// Emulates an instruction due to a memory access exit.

openhcl/virt_mshv_vtl/src/processor/mshv/x64.rs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ use virt::x86::MsrError;
6464
use virt_support_x86emu::emulate::EmuCheckVtlAccessError;
6565
use virt_support_x86emu::emulate::EmuTranslateError;
6666
use virt_support_x86emu::emulate::EmuTranslateResult;
67-
use virt_support_x86emu::emulate::EmulationPolicy;
6867
use virt_support_x86emu::emulate::EmulatorSupport;
6968
use x86defs::RFlags;
7069
use x86defs::SegmentRegister;
@@ -670,13 +669,7 @@ impl<'a, 'b> InterceptHandler<'a, 'b> {
670669

671670
let cache = self.vp.emulation_cache(self.intercepted_vtl);
672671
self.vp
673-
.emulate(
674-
dev,
675-
interruption_pending,
676-
self.intercepted_vtl,
677-
cache,
678-
EmulationPolicy::EmulateAll,
679-
)
672+
.emulate(dev, interruption_pending, self.intercepted_vtl, cache)
680673
.await?;
681674
Ok(())
682675
}
@@ -700,13 +693,7 @@ impl<'a, 'b> InterceptHandler<'a, 'b> {
700693
if message.access_info.string_op() || message.access_info.rep_prefix() {
701694
let cache = self.vp.emulation_cache(self.intercepted_vtl);
702695
self.vp
703-
.emulate(
704-
dev,
705-
interruption_pending,
706-
self.intercepted_vtl,
707-
cache,
708-
EmulationPolicy::EmulateAll,
709-
)
696+
.emulate(dev, interruption_pending, self.intercepted_vtl, cache)
710697
.await
711698
} else {
712699
let next_rip = next_rip(&message.header);
@@ -1176,10 +1163,6 @@ impl<T: CpuIo> EmulatorSupport for UhEmulationState<'_, '_, T, HypervisorBackedX
11761163
}
11771164
}
11781165

1179-
fn vtom(&self) -> Option<u64> {
1180-
None
1181-
}
1182-
11831166
fn initial_gva_translation(&self) -> Option<virt_support_x86emu::emulate::InitialTranslation> {
11841167
if (self.vp.runner.exit_message().header.typ != HvMessageType::HvMessageTypeGpaIntercept)
11851168
&& (self.vp.runner.exit_message().header.typ != HvMessageType::HvMessageTypeUnmappedGpa)

openhcl/virt_mshv_vtl/src/processor/snp/mod.rs

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ use crate::WakeReason;
2626
use crate::devmsr;
2727
use crate::processor::UhHypercallHandler;
2828
use crate::processor::UhProcessor;
29-
use guestmem::GuestMemory;
3029
use hcl::vmsa::VmsaWrapper;
3130
use hv1_emulator::hv::ProcessorVtlHv;
3231
use hv1_emulator::synic::ProcessorSynic;
@@ -61,9 +60,7 @@ use virt::x86::MsrErrorExt;
6160
use virt::x86::SegmentRegister;
6261
use virt::x86::TableRegister;
6362
use virt_support_apic::ApicClient;
64-
use virt_support_x86emu::emulate::EmulationPolicy;
6563
use virt_support_x86emu::emulate::EmulatorSupport as X86EmulatorSupport;
66-
use virt_support_x86emu::emulate::ProbeResult;
6764
use virt_support_x86emu::emulate::emulate_io;
6865
use virt_support_x86emu::emulate::emulate_translate_gva;
6966
use virt_support_x86emu::translate::TranslationRegisters;
@@ -1317,14 +1314,8 @@ impl UhProcessor<'_, SnpBacked> {
13171314
// to also check for io port installation, mainly for
13181315
// handling rep instructions.
13191316

1320-
self.emulate(
1321-
dev,
1322-
interruption_pending,
1323-
entered_from_vtl,
1324-
(),
1325-
EmulationPolicy::EmulateAll,
1326-
)
1327-
.await?;
1317+
self.emulate(dev, interruption_pending, entered_from_vtl, ())
1318+
.await?;
13281319
} else {
13291320
let mut rax = vmsa.rax();
13301321
emulate_io(
@@ -1420,14 +1411,8 @@ impl UhProcessor<'_, SnpBacked> {
14201411

14211412
if emulate {
14221413
has_intercept = false;
1423-
self.emulate(
1424-
dev,
1425-
interruption_pending,
1426-
entered_from_vtl,
1427-
(),
1428-
EmulationPolicy::ProbeGpa(&self.partition.lower_vtl_memory_layout),
1429-
)
1430-
.await?;
1414+
self.emulate(dev, interruption_pending, entered_from_vtl, ())
1415+
.await?;
14311416
&mut self.backing.exit_stats[entered_from_vtl].npf
14321417
} else {
14331418
&mut self.backing.exit_stats[entered_from_vtl].npf_spurious
@@ -1755,19 +1740,6 @@ impl<T: CpuIo> X86EmulatorSupport for UhEmulationState<'_, '_, T, SnpBacked> {
17551740
Some(self.vp.runner.vmsa(self.vtl).exit_info2())
17561741
}
17571742

1758-
fn vtom(&self) -> Option<u64> {
1759-
self.vp.partition.caps.vtom
1760-
}
1761-
1762-
fn probe_ram(&self, _gpa: u64, _gm: &GuestMemory) -> ProbeResult {
1763-
// TODO SNP: Implement these probe checks similar to TDX.
1764-
ProbeResult::Emulate
1765-
}
1766-
1767-
fn probe_none(&self, _gpa: u64) -> ProbeResult {
1768-
ProbeResult::InjectMachineCheck
1769-
}
1770-
17711743
fn initial_gva_translation(&self) -> Option<virt_support_x86emu::emulate::InitialTranslation> {
17721744
None
17731745
}

openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs

Lines changed: 91 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use crate::UhPartitionInner;
2323
use crate::UhPartitionNewParams;
2424
use crate::UhProcessor;
2525
use crate::WakeReason;
26-
use guestmem::GuestMemory;
2726
use hcl::ioctl::ProcessorRunner;
2827
use hcl::ioctl::tdx::Tdx;
2928
use hcl::ioctl::tdx::TdxPrivateRegs;
@@ -69,14 +68,13 @@ use virt::x86::TableRegister;
6968
use virt_support_apic::ApicClient;
7069
use virt_support_apic::OffloadNotSupported;
7170
use virt_support_x86emu::emulate::EmulatedMemoryOperation;
72-
use virt_support_x86emu::emulate::EmulationPolicy;
7371
use virt_support_x86emu::emulate::EmulatorSupport as X86EmulatorSupport;
74-
use virt_support_x86emu::emulate::ProbeResult;
7572
use virt_support_x86emu::emulate::TranslateMode;
7673
use virt_support_x86emu::emulate::emulate_insn_memory_op;
7774
use virt_support_x86emu::emulate::emulate_io;
7875
use virt_support_x86emu::emulate::emulate_translate_gva;
7976
use virt_support_x86emu::translate::TranslationRegisters;
77+
use vm_topology::memory::AddressType;
8078
use vmcore::vmtime::VmTimeAccess;
8179
use x86defs::RFlags;
8280
use x86defs::X64_CR0_ET;
@@ -1770,7 +1768,6 @@ impl UhProcessor<'_, TdxBacked> {
17701768
.valid(),
17711769
intercepted_vtl,
17721770
TdxEmulationCache::default(),
1773-
EmulationPolicy::EmulateAll,
17741771
)
17751772
.await?;
17761773
} else {
@@ -2001,6 +1998,7 @@ impl UhProcessor<'_, TdxBacked> {
20011998
&mut self.backing.vtls[intercepted_vtl].exit_stats.wbinvd
20021999
}
20032000
VmxExitBasic::EPT_VIOLATION => {
2001+
let gpa = exit_info.gpa();
20042002
let ept_info = VmxEptExitQualification::from(exit_info.qualification());
20052003
// If this was an EPT violation while handling an iret, and
20062004
// that iret cleared the NMI blocking state, restore it.
@@ -2018,16 +2016,7 @@ impl UhProcessor<'_, TdxBacked> {
20182016
.into();
20192017
assert!(!old_interruptibility.blocked_by_nmi());
20202018
} else {
2021-
self.emulate(
2022-
dev,
2023-
self.backing.vtls[intercepted_vtl]
2024-
.interruption_information
2025-
.valid(),
2026-
intercepted_vtl,
2027-
TdxEmulationCache::default(),
2028-
EmulationPolicy::ProbeGpa(&self.partition.lower_vtl_memory_layout),
2029-
)
2030-
.await?;
2019+
self.handle_ept(intercepted_vtl, dev, gpa, ept_info).await?;
20312020
}
20322021

20332022
&mut self.backing.vtls[intercepted_vtl].exit_stats.ept_violation
@@ -2372,6 +2361,94 @@ impl UhProcessor<'_, TdxBacked> {
23722361
self.backing.vtls[vtl].exception_error_code = 0;
23732362
}
23742363

2364+
fn inject_mc(&mut self, vtl: GuestVtl) {
2365+
self.backing.vtls[vtl].interruption_information = InterruptionInformation::new()
2366+
.with_valid(true)
2367+
.with_vector(x86defs::Exception::MACHINE_CHECK.0)
2368+
.with_interruption_type(INTERRUPT_TYPE_HARDWARE_EXCEPTION);
2369+
}
2370+
2371+
async fn handle_ept(
2372+
&mut self,
2373+
intercepted_vtl: GuestVtl,
2374+
dev: &impl CpuIo,
2375+
gpa: u64,
2376+
ept_info: VmxEptExitQualification,
2377+
) -> Result<(), VpHaltReason<UhRunVpError>> {
2378+
// vtom may be 0 if we are hiding isolation
2379+
let vtom = self.partition.caps.vtom.unwrap_or(0);
2380+
let is_shared = (gpa & vtom) == vtom && vtom != 0;
2381+
let canonical_gpa = gpa & !vtom;
2382+
2383+
// Only emulate the access if the gpa is expected to be accessible. This
2384+
// means, the gpa was described to VTL0 in some form as memory or mmio,
2385+
// and the hardware did not generate an exit for a private/shared
2386+
// violation.
2387+
let address_type = self
2388+
.partition
2389+
.lower_vtl_memory_layout
2390+
.probe_address(canonical_gpa);
2391+
2392+
match address_type {
2393+
Some(AddressType::Mmio) => {
2394+
// Emulate the access.
2395+
self.emulate(
2396+
dev,
2397+
self.backing.vtls[intercepted_vtl]
2398+
.interruption_information
2399+
.valid(),
2400+
intercepted_vtl,
2401+
TdxEmulationCache::default(),
2402+
)
2403+
.await?;
2404+
}
2405+
Some(AddressType::Ram) => {
2406+
// TODO TDX: This path changes when we support VTL page
2407+
// protections and MNF. That will require injecting events to
2408+
// VTL1 or other handling.
2409+
//
2410+
// For now, we just check if the exit was suprious or if we
2411+
// should inject a machine check. An exit is considered spurious
2412+
// if the gpa is accessible.
2413+
if self.partition.gm[intercepted_vtl].check_gpa_readable(gpa) {
2414+
tracelimit::warn_ratelimited!(gpa, "possible spurious EPT violation, ignoring");
2415+
} else {
2416+
// TODO: It would be better to show what exact bitmap check
2417+
// failed, but that requires some refactoring of how the
2418+
// different bitmaps are stored. Do this when we support VTL
2419+
// protections or MNF.
2420+
//
2421+
// If we entered this path, it means the bitmap check on
2422+
// `check_gpa_readable` failed so we can assume that if the
2423+
// address is shared, the actual state of the page is
2424+
// private, and vice versa. This is because the address
2425+
// should have already been checked to be valid memory
2426+
// described to the guest or not.
2427+
tracelimit::warn_ratelimited!(
2428+
gpa,
2429+
is_shared,
2430+
?ept_info,
2431+
"guest accessed inaccessible gpa, injecting MC"
2432+
);
2433+
self.inject_mc(intercepted_vtl);
2434+
}
2435+
}
2436+
None => {
2437+
// The guest should never attempt to access address that are not
2438+
// described in mmio or ram. Inject a machine check.
2439+
tracelimit::warn_ratelimited!(
2440+
gpa,
2441+
is_shared,
2442+
?ept_info,
2443+
"guest accessed gpa not described in memory layout, injecting MC"
2444+
);
2445+
self.inject_mc(intercepted_vtl);
2446+
}
2447+
}
2448+
2449+
Ok(())
2450+
}
2451+
23752452
fn handle_tdvmcall(&mut self, dev: &impl CpuIo, intercepted_vtl: GuestVtl) {
23762453
let regs = self.runner.tdx_enter_guest_gps();
23772454
if regs[TdxGp::R10] == 0 {
@@ -2778,63 +2855,6 @@ impl<T: CpuIo> X86EmulatorSupport for UhEmulationState<'_, '_, T, TdxBacked> {
27782855
Some(TdxExit(self.vp.runner.tdx_vp_enter_exit_info()).gpa())
27792856
}
27802857

2781-
fn vtom(&self) -> Option<u64> {
2782-
self.vp.partition.caps.vtom
2783-
}
2784-
2785-
fn probe_ram(&self, gpa: u64, gm: &GuestMemory) -> ProbeResult {
2786-
let vtom = self.vtom().unwrap_or(0);
2787-
let is_shared = (gpa & vtom) == vtom && vtom != 0;
2788-
2789-
// TODO TDX: This path changes when we support VTL page
2790-
// protections and MNF. That will require injecting events to
2791-
// VTL1 or other handling.
2792-
//
2793-
// For now, we just check if the exit was suprious or if we
2794-
// should inject a machine check. An exit is considered spurious
2795-
// if the gpa is accessible.
2796-
if gm.check_gpa_readable(gpa) {
2797-
tracelimit::warn_ratelimited!(
2798-
is_shared,
2799-
gpa,
2800-
"possible spurious EPT violation, ignoring"
2801-
);
2802-
ProbeResult::Ignore
2803-
} else {
2804-
// TODO: It would be better to show what exact bitmap check
2805-
// failed, but that requires some refactoring of how the
2806-
// different bitmaps are stored. Do this when we support VTL
2807-
// protections or MNF.
2808-
//
2809-
// If we entered this path, it means the bitmap check on
2810-
// `check_gpa_readable` failed so we can assume that if the
2811-
// address is shared, the actual state of the page is
2812-
// private, and vice versa. This is because the address
2813-
// should have already been checked to be valid memory
2814-
// described to the guest or not.
2815-
tracelimit::warn_ratelimited!(
2816-
gpa,
2817-
is_shared,
2818-
"guest accessed inaccessible gpa, injecting MC"
2819-
);
2820-
ProbeResult::InjectMachineCheck
2821-
}
2822-
}
2823-
2824-
fn probe_none(&self, gpa: u64) -> ProbeResult {
2825-
let vtom = self.vtom().unwrap_or(0);
2826-
let is_shared = (gpa & vtom) == vtom && vtom != 0;
2827-
2828-
// The guest should never attempt to access address that are not
2829-
// described in mmio or ram. Inject a machine check.
2830-
tracelimit::warn_ratelimited!(
2831-
gpa,
2832-
is_shared,
2833-
"guest accessed gpa not described in memory layout, injecting MC"
2834-
);
2835-
ProbeResult::InjectMachineCheck
2836-
}
2837-
28382858
fn initial_gva_translation(&self) -> Option<virt_support_x86emu::emulate::InitialTranslation> {
28392859
let exit_info = TdxExit(self.vp.runner.tdx_vp_enter_exit_info());
28402860
let ept_info = VmxEptExitQualification::from(exit_info.qualification());

vmm_core/virt_mshv/src/lib.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ use virt::irqcon::MsiRequest;
6969
use virt::x86::max_physical_address_size_from_cpuid;
7070
use virt_support_x86emu::emulate::EmuTranslateError;
7171
use virt_support_x86emu::emulate::EmuTranslateResult;
72-
use virt_support_x86emu::emulate::EmulationPolicy;
7372
use virt_support_x86emu::emulate::EmulatorSupport;
7473
use virt_support_x86emu::emulate::TranslateGvaSupport;
7574
use virt_support_x86emu::emulate::TranslateMode;
@@ -464,13 +463,7 @@ impl MshvProcessor<'_> {
464463
interruption_pending,
465464
cache,
466465
};
467-
virt_support_x86emu::emulate::emulate(
468-
&mut support,
469-
&self.partition.gm,
470-
devices,
471-
EmulationPolicy::EmulateAll,
472-
)
473-
.await
466+
virt_support_x86emu::emulate::emulate(&mut support, &self.partition.gm, devices).await
474467
}
475468

476469
async fn handle_io_port_intercept(
@@ -942,10 +935,6 @@ impl EmulatorSupport for MshvEmulationState<'_> {
942935
}
943936
}
944937

945-
fn vtom(&self) -> Option<u64> {
946-
None
947-
}
948-
949938
fn initial_gva_translation(&self) -> Option<virt_support_x86emu::emulate::InitialTranslation> {
950939
if (self.message.header.message_type != HvMessageType::HvMessageTypeGpaIntercept.0)
951940
&& (self.message.header.message_type != HvMessageType::HvMessageTypeUnmappedGpa.0)

0 commit comments

Comments
 (0)