use super::support::HypercallDispatch;
use super::support::HypercallParameters;
use super::support::RepHypercall;
use super::support::SimpleHypercall;
use super::support::VariableHypercall;
use super::support::VtlHypercall;
use crate::support::HvRepResult;
use crate::support::VariableRepHypercall;
use hv1_structs::ProcessorSet;
use hvdef::HvError;
use hvdef::HvMessage;
use hvdef::HvRegisterName;
use hvdef::HvRegisterValue;
use hvdef::HvResult;
use hvdef::HypercallCode;
use hvdef::Vtl;
use hvdef::hypercall as defs;
use hvdef::hypercall::AcceptPagesAttributes;
use hvdef::hypercall::HostVisibilityType;
use hvdef::hypercall::HvRegisterAssoc;
use hvdef::hypercall::HypercallOutput;
use hvdef::hypercall::VtlPermissionSet;
use zerocopy::IntoBytes;
pub trait PostMessage {
fn post_message(&mut self, connection_id: u32, message: &[u8]) -> HvResult<()>;
}
pub type HvPostMessage =
SimpleHypercall<defs::PostMessage, (), { HypercallCode::HvCallPostMessage.0 }>;
impl<T: PostMessage> HypercallDispatch<HvPostMessage> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvPostMessage::run(params, |input| {
self.post_message(
input.connection_id,
input
.payload
.as_bytes()
.get(..input.payload_size as usize)
.ok_or(HvError::InvalidParameter)?,
)
})
}
}
pub trait SignalEvent {
fn signal_event(&mut self, connection_id: u32, flag: u16) -> HvResult<()>;
}
pub type HvSignalEvent =
SimpleHypercall<defs::SignalEvent, (), { HypercallCode::HvCallSignalEvent.0 }>;
impl<T: SignalEvent> HypercallDispatch<HvSignalEvent> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvSignalEvent::run(params, |input| {
self.signal_event(input.connection_id, input.flag_number)
})
}
}
pub trait PostMessageDirect {
fn post_message_direct(
&mut self,
partition_id: u64,
target_vtl: Vtl,
vp: u32,
sint: u8,
message: &HvMessage,
) -> HvResult<()>;
}
pub type HvPostMessageDirect =
SimpleHypercall<defs::PostMessageDirect, (), { HypercallCode::HvCallPostMessageDirect.0 }>;
impl<T: PostMessageDirect> HypercallDispatch<HvPostMessageDirect> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvPostMessageDirect::run(params, |input| {
let message = input.message.get();
self.post_message_direct(
input.partition_id,
Vtl::try_from(input.vtl)?,
input.vp_index,
input.sint,
&message,
)
})
}
}
pub trait SignalEventDirect {
fn signal_event_direct(
&mut self,
partition_id: u64,
vtl: Vtl,
vp: u32,
sint: u8,
flag: u16,
) -> HvResult<defs::SignalEventDirectOutput>;
}
pub type HvSignalEventDirect = SimpleHypercall<
defs::SignalEventDirect,
defs::SignalEventDirectOutput,
{ HypercallCode::HvCallSignalEventDirect.0 },
>;
impl<T: SignalEventDirect> HypercallDispatch<HvSignalEventDirect> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvSignalEventDirect::run(params, |input| {
self.signal_event_direct(
input.target_partition,
Vtl::try_from(input.target_vtl)?,
input.target_vp,
input.target_sint,
input.flag_number,
)
})
}
}
pub trait RetargetDeviceInterrupt {
fn retarget_interrupt(
&mut self,
device_id: u64,
address: u64,
data: u32,
params: HvInterruptParameters<'_>,
) -> HvResult<()>;
}
pub struct HvInterruptParameters<'a> {
pub vector: u32,
pub multicast: bool,
pub target_processors: ProcessorSet<'a>,
}
pub type HvRetargetDeviceInterrupt = VariableHypercall<
defs::RetargetDeviceInterrupt,
(),
{ HypercallCode::HvCallRetargetDeviceInterrupt.0 },
>;
impl<T: RetargetDeviceInterrupt> HypercallDispatch<HvRetargetDeviceInterrupt> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvRetargetDeviceInterrupt::run(params, |input, var_input| {
if input.target_header.flags.reserved() != 0 {
return Err(HvError::InvalidParameter);
}
let masks = &[input.target_header.mask_or_format];
let target_processors = if input.target_header.flags.processor_set() {
ProcessorSet::from_generic_set(input.target_header.mask_or_format, var_input)
} else {
ProcessorSet::from_processor_masks(1, masks)
}
.ok_or(HvError::InvalidParameter)?;
if input.entry.source != defs::HvInterruptSource::MSI {
return Err(HvError::InvalidParameter);
}
self.retarget_interrupt(
input.device_id,
input.entry.data[0] as u64,
input.entry.data[1],
HvInterruptParameters {
vector: input.target_header.vector,
multicast: input.target_header.flags.multicast(),
target_processors,
},
)
})
}
}
pub type HvAssertVirtualInterrupt = SimpleHypercall<
defs::AssertVirtualInterrupt,
(),
{ HypercallCode::HvCallAssertVirtualInterrupt.0 },
>;
pub trait AssertVirtualInterrupt {
fn assert_virtual_interrupt(
&mut self,
partition_id: u64,
interrupt_control: hvdef::HvInterruptControl,
destination_address: u64,
requested_vector: u32,
target_vtl: Vtl,
) -> HvResult<()>;
}
impl<T: AssertVirtualInterrupt> HypercallDispatch<HvAssertVirtualInterrupt> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvAssertVirtualInterrupt::run(params, |input| {
self.assert_virtual_interrupt(
input.partition_id,
input.interrupt_control,
input.destination_address,
input.requested_vector,
input.target_vtl.try_into()?,
)
})
}
}
pub type HvX64StartVirtualProcessor = SimpleHypercall<
defs::StartVirtualProcessorX64,
(),
{ HypercallCode::HvCallStartVirtualProcessor.0 },
>;
pub trait StartVirtualProcessor<T> {
fn start_virtual_processor(
&mut self,
partition_id: u64,
vp_index: u32,
target_vtl: Vtl,
vp_context: &T,
) -> HvResult<()>;
}
impl<T: StartVirtualProcessor<defs::InitialVpContextX64>>
HypercallDispatch<HvX64StartVirtualProcessor> for T
{
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvX64StartVirtualProcessor::run(params, |input| {
self.start_virtual_processor(
input.partition_id,
input.vp_index,
Vtl::try_from(input.target_vtl)?,
&input.vp_context,
)
})
}
}
pub type HvArm64StartVirtualProcessor = SimpleHypercall<
defs::StartVirtualProcessorArm64,
(),
{ HypercallCode::HvCallStartVirtualProcessor.0 },
>;
impl<T: StartVirtualProcessor<defs::InitialVpContextArm64>>
HypercallDispatch<HvArm64StartVirtualProcessor> for T
{
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvArm64StartVirtualProcessor::run(params, |input| {
self.start_virtual_processor(
input.partition_id,
input.vp_index,
Vtl::try_from(input.target_vtl)?,
&input.vp_context,
)
})
}
}
pub type HvX64TranslateVirtualAddress = SimpleHypercall<
defs::TranslateVirtualAddressX64,
defs::TranslateVirtualAddressOutput,
{ HypercallCode::HvCallTranslateVirtualAddress.0 },
>;
pub trait TranslateVirtualAddressX64 {
fn translate_virtual_address(
&mut self,
partition_id: u64,
vp_index: u32,
control_flags: defs::TranslateGvaControlFlagsX64,
gva_page: u64,
) -> HvResult<defs::TranslateVirtualAddressOutput>;
}
impl<T: TranslateVirtualAddressX64> HypercallDispatch<HvX64TranslateVirtualAddress> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvX64TranslateVirtualAddress::run(params, |input| {
self.translate_virtual_address(
input.partition_id,
input.vp_index,
input.control_flags,
input.gva_page,
)
})
}
}
pub type HvX64TranslateVirtualAddressEx = SimpleHypercall<
defs::TranslateVirtualAddressX64,
defs::TranslateVirtualAddressExOutputX64,
{ HypercallCode::HvCallTranslateVirtualAddressEx.0 },
>;
pub trait TranslateVirtualAddressExX64 {
fn translate_virtual_address_ex(
&mut self,
partition_id: u64,
vp_index: u32,
control_flags: defs::TranslateGvaControlFlagsX64,
gva_page: u64,
) -> HvResult<defs::TranslateVirtualAddressExOutputX64>;
}
impl<T: TranslateVirtualAddressExX64> HypercallDispatch<HvX64TranslateVirtualAddressEx> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvX64TranslateVirtualAddressEx::run(params, |input| {
self.translate_virtual_address_ex(
input.partition_id,
input.vp_index,
input.control_flags,
input.gva_page,
)
})
}
}
pub type HvAarch64TranslateVirtualAddressEx = SimpleHypercall<
defs::TranslateVirtualAddressArm64,
defs::TranslateVirtualAddressExOutputArm64,
{ HypercallCode::HvCallTranslateVirtualAddressEx.0 },
>;
pub trait TranslateVirtualAddressExAarch64 {
fn translate_virtual_address_ex(
&mut self,
partition_id: u64,
vp_index: u32,
control_flags: defs::TranslateGvaControlFlagsArm64,
gva_page: u64,
) -> HvResult<defs::TranslateVirtualAddressExOutputArm64>;
}
impl<T: TranslateVirtualAddressExAarch64> HypercallDispatch<HvAarch64TranslateVirtualAddressEx>
for T
{
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvAarch64TranslateVirtualAddressEx::run(params, |input| {
self.translate_virtual_address_ex(
input.partition_id,
input.vp_index,
input.control_flags,
input.gva_page,
)
})
}
}
pub type HvGetVpRegisters = RepHypercall<
defs::GetSetVpRegisters,
HvRegisterName,
HvRegisterValue,
{ HypercallCode::HvCallGetVpRegisters.0 },
>;
pub trait GetVpRegisters {
fn get_vp_registers(
&mut self,
partition_id: u64,
vp_index: u32,
vtl: Option<Vtl>,
registers: &[HvRegisterName],
output: &mut [HvRegisterValue],
) -> HvRepResult;
}
impl<T: GetVpRegisters> HypercallDispatch<HvGetVpRegisters> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvGetVpRegisters::run(params, |header, input, output| {
self.get_vp_registers(
header.partition_id,
header.vp_index,
header.target_vtl.target_vtl().map_err(|err| (err, 0))?,
input,
output,
)
})
}
}
pub type HvSetVpRegisters = RepHypercall<
defs::GetSetVpRegisters,
HvRegisterAssoc,
(),
{ HypercallCode::HvCallSetVpRegisters.0 },
>;
pub trait SetVpRegisters {
fn set_vp_registers(
&mut self,
partition_id: u64,
vp_index: u32,
vtl: Option<Vtl>,
registers: &[HvRegisterAssoc],
) -> HvRepResult;
}
impl<T: SetVpRegisters> HypercallDispatch<HvSetVpRegisters> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvSetVpRegisters::run(params, |header, input, _output| {
self.set_vp_registers(
header.partition_id,
header.vp_index,
header.target_vtl.target_vtl().map_err(|err| (err, 0))?,
input,
)
})
}
}
pub trait InstallIntercept {
fn install_intercept(
&mut self,
partition_id: u64,
access_type_mask: u32,
intercept_type: defs::HvInterceptType,
intercept_parameters: defs::HvInterceptParameters,
) -> HvResult<()>;
}
pub type HvInstallIntercept =
SimpleHypercall<defs::InstallIntercept, (), { HypercallCode::HvCallInstallIntercept.0 }>;
impl<T: InstallIntercept> HypercallDispatch<HvInstallIntercept> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvInstallIntercept::run(params, |input| {
self.install_intercept(
input.partition_id,
input.access_type_mask,
input.intercept_type,
input.intercept_parameters,
)
})
}
}
pub trait VtlSwitchOps {
fn advance_ip(&mut self);
fn inject_invalid_opcode_fault(&mut self);
}
pub trait VtlReturn {
fn is_vtl_return_allowed(&self) -> bool;
fn vtl_return(&mut self, fast: bool);
}
pub type HvVtlReturn = VtlHypercall<{ HypercallCode::HvCallVtlReturn.0 }>;
impl<T: VtlReturn + VtlSwitchOps> HypercallDispatch<HvVtlReturn> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvVtlReturn::run(params, |input, control| {
if u64::from(control.with_code(0)) == 0
&& (input & !1) == 0
&& self.is_vtl_return_allowed()
{
self.advance_ip();
self.vtl_return(input & 1 != 0);
} else {
self.inject_invalid_opcode_fault();
}
})
}
}
pub trait VtlCall {
fn is_vtl_call_allowed(&self) -> bool;
fn vtl_call(&mut self);
}
pub type HvVtlCall = VtlHypercall<{ HypercallCode::HvCallVtlCall.0 }>;
impl<T: VtlCall + VtlSwitchOps> HypercallDispatch<HvVtlCall> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvVtlCall::run(params, |input, control| {
if u64::from(control.with_code(0)) == 0 && input == 0 && self.is_vtl_call_allowed() {
self.advance_ip();
self.vtl_call();
} else {
self.inject_invalid_opcode_fault();
}
})
}
}
pub trait EnableVpVtl<T> {
fn enable_vp_vtl(
&mut self,
partition_id: u64,
vp_index: u32,
vtl: Vtl,
vp_context: &T,
) -> HvResult<()>;
}
pub type HvX64EnableVpVtl =
SimpleHypercall<defs::EnableVpVtlX64, (), { HypercallCode::HvCallEnableVpVtl.0 }>;
impl<T: EnableVpVtl<hvdef::hypercall::InitialVpContextX64>> HypercallDispatch<HvX64EnableVpVtl>
for T
{
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvX64EnableVpVtl::run(params, |input| {
self.enable_vp_vtl(
input.partition_id,
input.vp_index,
Vtl::try_from(input.target_vtl)?,
&input.vp_vtl_context,
)
})
}
}
pub type HvArm64EnableVpVtl =
SimpleHypercall<defs::EnableVpVtlArm64, (), { HypercallCode::HvCallEnableVpVtl.0 }>;
impl<T: EnableVpVtl<hvdef::hypercall::InitialVpContextArm64>> HypercallDispatch<HvArm64EnableVpVtl>
for T
{
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvArm64EnableVpVtl::run(params, |input| {
self.enable_vp_vtl(
input.partition_id,
input.vp_index,
Vtl::try_from(input.target_vtl)?,
&input.vp_vtl_context,
)
})
}
}
pub trait ModifyVtlProtectionMask {
fn modify_vtl_protection_mask(
&mut self,
partition_id: u64,
map_flags: hvdef::HvMapGpaFlags,
target_vtl: Option<Vtl>,
gpa_pages: &[u64],
) -> HvRepResult;
}
pub type HvModifyVtlProtectionMask = RepHypercall<
defs::ModifyVtlProtectionMask,
u64,
(),
{ HypercallCode::HvCallModifyVtlProtectionMask.0 },
>;
impl<T: ModifyVtlProtectionMask> HypercallDispatch<HvModifyVtlProtectionMask> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvModifyVtlProtectionMask::run(params, |header, input, _output| {
self.modify_vtl_protection_mask(
header.partition_id,
header.map_flags,
header.target_vtl.target_vtl().map_err(|err| (err, 0))?,
input,
)
})
}
}
pub trait GetVpIndexFromApicId {
fn get_vp_index_from_apic_id(
&mut self,
partition_id: u64,
target_vtl: Vtl,
apic_ids: &[u32],
vp_indices: &mut [u32],
) -> HvRepResult;
}
pub type HvGetVpIndexFromApicId = RepHypercall<
defs::GetVpIndexFromApicId,
u32,
u32,
{ HypercallCode::HvCallGetVpIndexFromApicId.0 },
>;
impl<T: GetVpIndexFromApicId> HypercallDispatch<HvGetVpIndexFromApicId> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvGetVpIndexFromApicId::run(params, |header, input, output| {
self.get_vp_index_from_apic_id(
header.partition_id,
Vtl::try_from(header.target_vtl).map_err(|err| (err, 0))?,
input,
output,
)
})
}
}
pub trait AcceptGpaPages {
fn accept_gpa_pages(
&mut self,
partition_id: u64,
page_attributes: AcceptPagesAttributes,
vtl_permission_set: VtlPermissionSet,
gpa_page_base: u64,
page_count: usize,
) -> HvRepResult;
}
pub type HvAcceptGpaPages =
RepHypercall<defs::AcceptGpaPages, u64, (), { HypercallCode::HvCallAcceptGpaPages.0 }>;
impl<T: AcceptGpaPages> HypercallDispatch<HvAcceptGpaPages> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvAcceptGpaPages::run(params, |header, input, _output| {
self.accept_gpa_pages(
header.partition_id,
header.page_attributes,
header.vtl_permission_set,
header.gpa_page_base,
input.len(),
)
})
}
}
pub trait ModifySparseGpaPageHostVisibility {
fn modify_gpa_visibility(
&mut self,
partition_id: u64,
visibility: HostVisibilityType,
gpa_pages: &[u64],
) -> HvRepResult;
}
pub type HvModifySparseGpaPageHostVisibility = RepHypercall<
defs::ModifySparsePageVisibility,
u64,
(),
{ HypercallCode::HvCallModifySparseGpaPageHostVisibility.0 },
>;
impl<T: ModifySparseGpaPageHostVisibility> HypercallDispatch<HvModifySparseGpaPageHostVisibility>
for T
{
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvModifySparseGpaPageHostVisibility::run(params, |header, input, _output| {
self.modify_gpa_visibility(
header.partition_id,
header.host_visibility.host_visibility(),
input,
)
})
}
}
pub trait EnablePartitionVtl {
fn enable_partition_vtl(
&mut self,
partition_id: u64,
target_vtl: Vtl,
flags: defs::EnablePartitionVtlFlags,
) -> HvResult<()>;
}
pub type HvEnablePartitionVtl =
SimpleHypercall<defs::EnablePartitionVtl, (), { HypercallCode::HvCallEnablePartitionVtl.0 }>;
impl<T: EnablePartitionVtl> HypercallDispatch<HvEnablePartitionVtl> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvEnablePartitionVtl::run(params, |input| {
self.enable_partition_vtl(
input.partition_id,
Vtl::try_from(input.target_vtl).map_err(|_| HvError::AccessDenied)?,
input.flags,
)
})
}
}
pub trait FlushVirtualAddressList {
fn flush_virtual_address_list(
&mut self,
processor_set: ProcessorSet<'_>,
flags: defs::HvFlushFlags,
gva_ranges: &[defs::HvGvaRange],
) -> HvRepResult;
}
pub type HvFlushVirtualAddressList = RepHypercall<
defs::FlushVirtualAddressSpace,
defs::HvGvaRange,
(),
{ HypercallCode::HvCallFlushVirtualAddressList.0 },
>;
impl<T: FlushVirtualAddressList> HypercallDispatch<HvFlushVirtualAddressList> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvFlushVirtualAddressList::run(params, |header, input, _output| {
let masks = &[header.processor_mask];
let processors = ProcessorSet::from_processor_masks(1, masks)
.ok_or((HvError::InvalidParameter, 0))?;
self.flush_virtual_address_list(processors, header.flags, input)
})
}
}
pub trait FlushVirtualAddressListEx {
fn flush_virtual_address_list_ex(
&mut self,
processor_set: ProcessorSet<'_>,
flags: defs::HvFlushFlags,
gva_ranges: &[defs::HvGvaRange],
) -> HvRepResult;
}
pub type HvFlushVirtualAddressListEx = VariableRepHypercall<
defs::FlushVirtualAddressSpaceEx,
defs::HvGvaRange,
(),
{ HypercallCode::HvCallFlushVirtualAddressListEx.0 },
>;
impl<T: FlushVirtualAddressListEx> HypercallDispatch<HvFlushVirtualAddressListEx> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvFlushVirtualAddressListEx::run(params, |header, variable_input, input, _output| {
let processors =
ProcessorSet::from_generic_set(variable_input[0], &variable_input[1..])
.ok_or((HvError::InvalidParameter, 0))?;
self.flush_virtual_address_list_ex(processors, header.flags, input)
})
}
}
pub trait FlushVirtualAddressSpace {
fn flush_virtual_address_space(
&mut self,
processor_set: ProcessorSet<'_>,
flags: defs::HvFlushFlags,
) -> HvResult<()>;
}
pub type HvFlushVirtualAddressSpace = SimpleHypercall<
defs::FlushVirtualAddressSpace,
(),
{ HypercallCode::HvCallFlushVirtualAddressSpace.0 },
>;
impl<T: FlushVirtualAddressSpace> HypercallDispatch<HvFlushVirtualAddressSpace> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvFlushVirtualAddressSpace::run(params, |input| {
let masks = &[input.processor_mask];
let processors =
ProcessorSet::from_processor_masks(1, masks).ok_or(HvError::InvalidParameter)?;
self.flush_virtual_address_space(processors, input.flags)
})
}
}
pub trait FlushVirtualAddressSpaceEx {
fn flush_virtual_address_space_ex(
&mut self,
processor_set: ProcessorSet<'_>,
flags: defs::HvFlushFlags,
) -> HvResult<()>;
}
pub type HvFlushVirtualAddressSpaceEx = VariableHypercall<
defs::FlushVirtualAddressSpaceEx,
(),
{ HypercallCode::HvCallFlushVirtualAddressSpaceEx.0 },
>;
impl<T: FlushVirtualAddressSpaceEx> HypercallDispatch<HvFlushVirtualAddressSpaceEx> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvFlushVirtualAddressSpaceEx::run(params, |header, input| {
let processors = ProcessorSet::from_generic_set(input[0], &input[1..])
.ok_or(HvError::InvalidParameter)?;
self.flush_virtual_address_space_ex(processors, header.flags)
})
}
}
pub trait QuerySparseGpaPageHostVisibility {
fn query_gpa_visibility(
&mut self,
partition_id: u64,
gpa_pages: &[u64],
host_visibility: &mut [HostVisibilityType],
) -> HvRepResult;
}
pub type HvQuerySparseGpaPageHostVisibility = RepHypercall<
defs::QuerySparsePageVisibility,
u64,
HostVisibilityType,
{ HypercallCode::HvCallQuerySparseGpaPageHostVisibility.0 },
>;
impl<T: QuerySparseGpaPageHostVisibility> HypercallDispatch<HvQuerySparseGpaPageHostVisibility>
for T
{
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvQuerySparseGpaPageHostVisibility::run(params, |header, input, output| {
self.query_gpa_visibility(header.partition_id, input, output)
})
}
}
pub trait ExtendedQueryCapabilities {
fn query_extended_capabilities(&mut self) -> HvResult<u64>;
}
pub type HvExtQueryCapabilities =
SimpleHypercall<(), u64, { HypercallCode::HvExtCallQueryCapabilities.0 }>;
impl<T: ExtendedQueryCapabilities> HypercallDispatch<HvExtQueryCapabilities> for T {
fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
HvExtQueryCapabilities::run(params, |()| self.query_extended_capabilities())
}
}