1use super::support::HypercallDispatch;
7use super::support::HypercallParameters;
8use super::support::RepHypercall;
9use super::support::SimpleHypercall;
10use super::support::VariableHypercall;
11use super::support::VtlHypercall;
12use crate::support::HvRepResult;
13use crate::support::VariableRepHypercall;
14use hv1_structs::ProcessorSet;
15use hvdef::HvError;
16use hvdef::HvMessage;
17use hvdef::HvRegisterName;
18use hvdef::HvRegisterValue;
19use hvdef::HvResult;
20use hvdef::HypercallCode;
21use hvdef::Vtl;
22use hvdef::hypercall as defs;
23use hvdef::hypercall::AcceptPagesAttributes;
24use hvdef::hypercall::HostVisibilityType;
25use hvdef::hypercall::HvRegisterAssoc;
26use hvdef::hypercall::HypercallOutput;
27use hvdef::hypercall::VtlPermissionSet;
28use zerocopy::IntoBytes;
29
30pub trait PostMessage {
32 fn post_message(&mut self, connection_id: u32, message: &[u8]) -> HvResult<()>;
34}
35
36pub type HvPostMessage =
38 SimpleHypercall<defs::PostMessage, (), { HypercallCode::HvCallPostMessage.0 }>;
39
40impl<T: PostMessage> HypercallDispatch<HvPostMessage> for T {
41 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
42 HvPostMessage::run(params, |input| {
43 self.post_message(
44 input.connection_id,
45 input
46 .payload
47 .as_bytes()
48 .get(..input.payload_size as usize)
49 .ok_or(HvError::InvalidParameter)?,
50 )
51 })
52 }
53}
54
55pub trait SignalEvent {
57 fn signal_event(&mut self, connection_id: u32, flag: u16) -> HvResult<()>;
59}
60
61pub type HvSignalEvent =
63 SimpleHypercall<defs::SignalEvent, (), { HypercallCode::HvCallSignalEvent.0 }>;
64
65impl<T: SignalEvent> HypercallDispatch<HvSignalEvent> for T {
66 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
67 HvSignalEvent::run(params, |input| {
68 self.signal_event(input.connection_id, input.flag_number)
69 })
70 }
71}
72
73pub trait PostMessageDirect {
75 fn post_message_direct(
77 &mut self,
78 partition_id: u64,
79 target_vtl: Vtl,
80 vp: u32,
81 sint: u8,
82 message: &HvMessage,
83 ) -> HvResult<()>;
84}
85
86pub type HvPostMessageDirect =
88 SimpleHypercall<defs::PostMessageDirect, (), { HypercallCode::HvCallPostMessageDirect.0 }>;
89
90impl<T: PostMessageDirect> HypercallDispatch<HvPostMessageDirect> for T {
91 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
92 HvPostMessageDirect::run(params, |input| {
93 let message = input.message.get();
94 self.post_message_direct(
95 input.partition_id,
96 Vtl::try_from(input.vtl)?,
97 input.vp_index,
98 input.sint,
99 &message,
100 )
101 })
102 }
103}
104
105pub trait SignalEventDirect {
107 fn signal_event_direct(
109 &mut self,
110 partition_id: u64,
111 vtl: Vtl,
112 vp: u32,
113 sint: u8,
114 flag: u16,
115 ) -> HvResult<defs::SignalEventDirectOutput>;
116}
117
118pub type HvSignalEventDirect = SimpleHypercall<
120 defs::SignalEventDirect,
121 defs::SignalEventDirectOutput,
122 { HypercallCode::HvCallSignalEventDirect.0 },
123>;
124
125impl<T: SignalEventDirect> HypercallDispatch<HvSignalEventDirect> for T {
126 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
127 HvSignalEventDirect::run(params, |input| {
128 self.signal_event_direct(
129 input.target_partition,
130 Vtl::try_from(input.target_vtl)?,
131 input.target_vp,
132 input.target_sint,
133 input.flag_number,
134 )
135 })
136 }
137}
138
139pub trait RetargetDeviceInterrupt {
141 fn retarget_interrupt(
143 &mut self,
144 device_id: u64,
145 address: u64,
146 data: u32,
147 params: HvInterruptParameters<'_>,
148 ) -> HvResult<()>;
149}
150
151pub struct HvInterruptParameters<'a> {
153 pub vector: u32,
155 pub multicast: bool,
157 pub target_processors: ProcessorSet<'a>,
159}
160
161pub type HvRetargetDeviceInterrupt = VariableHypercall<
163 defs::RetargetDeviceInterrupt,
164 (),
165 { HypercallCode::HvCallRetargetDeviceInterrupt.0 },
166>;
167
168impl<T: RetargetDeviceInterrupt> HypercallDispatch<HvRetargetDeviceInterrupt> for T {
169 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
170 HvRetargetDeviceInterrupt::run(params, |input, var_input| {
171 if input.target_header.flags.reserved() != 0 {
172 return Err(HvError::InvalidParameter);
173 }
174
175 let masks = &[input.target_header.mask_or_format];
176 let target_processors = if input.target_header.flags.processor_set() {
177 ProcessorSet::from_generic_set(input.target_header.mask_or_format, var_input)
178 } else {
179 ProcessorSet::from_processor_masks(1, masks)
180 }
181 .ok_or(HvError::InvalidParameter)?;
182
183 if input.entry.source != defs::HvInterruptSource::MSI {
184 return Err(HvError::InvalidParameter);
185 }
186
187 self.retarget_interrupt(
188 input.device_id,
189 input.entry.data[0] as u64,
190 input.entry.data[1],
191 HvInterruptParameters {
192 vector: input.target_header.vector,
193 multicast: input.target_header.flags.multicast(),
194 target_processors,
195 },
196 )
197 })
198 }
199}
200
201pub type HvAssertVirtualInterrupt = SimpleHypercall<
203 defs::AssertVirtualInterrupt,
204 (),
205 { HypercallCode::HvCallAssertVirtualInterrupt.0 },
206>;
207
208pub trait AssertVirtualInterrupt {
210 fn assert_virtual_interrupt(
212 &mut self,
213 partition_id: u64,
214 interrupt_control: hvdef::HvInterruptControl,
215 destination_address: u64,
216 requested_vector: u32,
217 target_vtl: Vtl,
218 ) -> HvResult<()>;
219}
220
221impl<T: AssertVirtualInterrupt> HypercallDispatch<HvAssertVirtualInterrupt> for T {
222 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
223 HvAssertVirtualInterrupt::run(params, |input| {
224 if input.rsvd0 != 0 || input.rsvd1 != 0 {
225 return Err(HvError::InvalidParameter);
226 }
227 self.assert_virtual_interrupt(
228 input.partition_id,
229 input.interrupt_control,
230 input.destination_address,
231 input.requested_vector,
232 input.target_vtl.try_into()?,
233 )
234 })
235 }
236}
237
238pub type HvX64StartVirtualProcessor = SimpleHypercall<
240 defs::StartVirtualProcessorX64,
241 (),
242 { HypercallCode::HvCallStartVirtualProcessor.0 },
243>;
244
245pub trait StartVirtualProcessor<T> {
247 fn start_virtual_processor(
249 &mut self,
250 partition_id: u64,
251 vp_index: u32,
252 target_vtl: Vtl,
253 vp_context: &T,
254 ) -> HvResult<()>;
255}
256
257impl<T: StartVirtualProcessor<defs::InitialVpContextX64>>
258 HypercallDispatch<HvX64StartVirtualProcessor> for T
259{
260 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
261 HvX64StartVirtualProcessor::run(params, |input| {
262 if input.rsvd0 != 0 || input.rsvd1 != 0 {
263 return Err(HvError::InvalidParameter);
264 }
265 self.start_virtual_processor(
266 input.partition_id,
267 input.vp_index,
268 Vtl::try_from(input.target_vtl)?,
269 &input.vp_context,
270 )
271 })
272 }
273}
274
275pub type HvArm64StartVirtualProcessor = SimpleHypercall<
277 defs::StartVirtualProcessorArm64,
278 (),
279 { HypercallCode::HvCallStartVirtualProcessor.0 },
280>;
281
282impl<T: StartVirtualProcessor<defs::InitialVpContextArm64>>
283 HypercallDispatch<HvArm64StartVirtualProcessor> for T
284{
285 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
286 HvArm64StartVirtualProcessor::run(params, |input| {
287 self.start_virtual_processor(
288 input.partition_id,
289 input.vp_index,
290 Vtl::try_from(input.target_vtl)?,
291 &input.vp_context,
292 )
293 })
294 }
295}
296
297pub type HvX64TranslateVirtualAddress = SimpleHypercall<
299 defs::TranslateVirtualAddressX64,
300 defs::TranslateVirtualAddressOutput,
301 { HypercallCode::HvCallTranslateVirtualAddress.0 },
302>;
303
304pub trait TranslateVirtualAddressX64 {
306 fn translate_virtual_address(
308 &mut self,
309 partition_id: u64,
310 vp_index: u32,
311 control_flags: defs::TranslateGvaControlFlagsX64,
312 gva_page: u64,
313 ) -> HvResult<defs::TranslateVirtualAddressOutput>;
314}
315
316impl<T: TranslateVirtualAddressX64> HypercallDispatch<HvX64TranslateVirtualAddress> for T {
317 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
318 HvX64TranslateVirtualAddress::run(params, |input| {
319 self.translate_virtual_address(
320 input.partition_id,
321 input.vp_index,
322 input.control_flags,
323 input.gva_page,
324 )
325 })
326 }
327}
328
329pub type HvX64TranslateVirtualAddressEx = SimpleHypercall<
331 defs::TranslateVirtualAddressX64,
332 defs::TranslateVirtualAddressExOutputX64,
333 { HypercallCode::HvCallTranslateVirtualAddressEx.0 },
334>;
335
336pub trait TranslateVirtualAddressExX64 {
338 fn translate_virtual_address_ex(
340 &mut self,
341 partition_id: u64,
342 vp_index: u32,
343 control_flags: defs::TranslateGvaControlFlagsX64,
344 gva_page: u64,
345 ) -> HvResult<defs::TranslateVirtualAddressExOutputX64>;
346}
347
348impl<T: TranslateVirtualAddressExX64> HypercallDispatch<HvX64TranslateVirtualAddressEx> for T {
349 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
350 HvX64TranslateVirtualAddressEx::run(params, |input| {
351 self.translate_virtual_address_ex(
352 input.partition_id,
353 input.vp_index,
354 input.control_flags,
355 input.gva_page,
356 )
357 })
358 }
359}
360
361pub type HvAarch64TranslateVirtualAddressEx = SimpleHypercall<
363 defs::TranslateVirtualAddressArm64,
364 defs::TranslateVirtualAddressExOutputArm64,
365 { HypercallCode::HvCallTranslateVirtualAddressEx.0 },
366>;
367
368pub trait TranslateVirtualAddressExAarch64 {
370 fn translate_virtual_address_ex(
372 &mut self,
373 partition_id: u64,
374 vp_index: u32,
375 control_flags: defs::TranslateGvaControlFlagsArm64,
376 gva_page: u64,
377 ) -> HvResult<defs::TranslateVirtualAddressExOutputArm64>;
378}
379
380impl<T: TranslateVirtualAddressExAarch64> HypercallDispatch<HvAarch64TranslateVirtualAddressEx>
381 for T
382{
383 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
384 HvAarch64TranslateVirtualAddressEx::run(params, |input| {
385 self.translate_virtual_address_ex(
386 input.partition_id,
387 input.vp_index,
388 input.control_flags,
389 input.gva_page,
390 )
391 })
392 }
393}
394
395pub type HvGetVpRegisters = RepHypercall<
397 defs::GetSetVpRegisters,
398 HvRegisterName,
399 HvRegisterValue,
400 { HypercallCode::HvCallGetVpRegisters.0 },
401>;
402
403pub trait GetVpRegisters {
405 fn get_vp_registers(
407 &mut self,
408 partition_id: u64,
409 vp_index: u32,
410 vtl: Option<Vtl>,
411 registers: &[HvRegisterName],
412 output: &mut [HvRegisterValue],
413 ) -> HvRepResult;
414}
415
416impl<T: GetVpRegisters> HypercallDispatch<HvGetVpRegisters> for T {
417 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
418 HvGetVpRegisters::run(params, |header, input, output| {
419 self.get_vp_registers(
420 header.partition_id,
421 header.vp_index,
422 header.target_vtl.target_vtl().map_err(|err| (err, 0))?,
423 input,
424 output,
425 )
426 })
427 }
428}
429
430pub type HvSetVpRegisters = RepHypercall<
432 defs::GetSetVpRegisters,
433 HvRegisterAssoc,
434 (),
435 { HypercallCode::HvCallSetVpRegisters.0 },
436>;
437
438pub trait SetVpRegisters {
440 fn set_vp_registers(
442 &mut self,
443 partition_id: u64,
444 vp_index: u32,
445 vtl: Option<Vtl>,
446 registers: &[HvRegisterAssoc],
447 ) -> HvRepResult;
448}
449
450impl<T: SetVpRegisters> HypercallDispatch<HvSetVpRegisters> for T {
451 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
452 HvSetVpRegisters::run(params, |header, input, _output| {
453 self.set_vp_registers(
454 header.partition_id,
455 header.vp_index,
456 header.target_vtl.target_vtl().map_err(|err| (err, 0))?,
457 input,
458 )
459 })
460 }
461}
462
463pub trait InstallIntercept {
465 fn install_intercept(
467 &mut self,
468 partition_id: u64,
469 access_type_mask: u32,
470 intercept_type: defs::HvInterceptType,
471 intercept_parameters: defs::HvInterceptParameters,
472 ) -> HvResult<()>;
473}
474
475pub type HvInstallIntercept =
477 SimpleHypercall<defs::InstallIntercept, (), { HypercallCode::HvCallInstallIntercept.0 }>;
478
479impl<T: InstallIntercept> HypercallDispatch<HvInstallIntercept> for T {
480 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
481 HvInstallIntercept::run(params, |input| {
482 self.install_intercept(
483 input.partition_id,
484 input.access_type_mask,
485 input.intercept_type,
486 input.intercept_parameters,
487 )
488 })
489 }
490}
491
492pub trait VtlSwitchOps {
494 fn advance_ip(&mut self);
497 fn inject_invalid_opcode_fault(&mut self);
500}
501
502pub trait VtlReturn {
504 fn is_vtl_return_allowed(&self) -> bool;
506
507 fn vtl_return(&mut self, fast: bool);
509}
510
511pub type HvVtlReturn = VtlHypercall<{ HypercallCode::HvCallVtlReturn.0 }>;
513
514impl<T: VtlReturn + VtlSwitchOps> HypercallDispatch<HvVtlReturn> for T {
515 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
516 HvVtlReturn::run(params, |input, control| {
517 if u64::from(control.with_code(0)) == 0
522 && (input & !1) == 0
523 && self.is_vtl_return_allowed()
524 {
525 self.advance_ip();
527 self.vtl_return(input & 1 != 0);
528 } else {
529 self.inject_invalid_opcode_fault();
531 }
532 })
533 }
534}
535
536pub trait VtlCall {
538 fn is_vtl_call_allowed(&self) -> bool;
540 fn vtl_call(&mut self);
542}
543
544pub type HvVtlCall = VtlHypercall<{ HypercallCode::HvCallVtlCall.0 }>;
546
547impl<T: VtlCall + VtlSwitchOps> HypercallDispatch<HvVtlCall> for T {
548 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
549 HvVtlCall::run(params, |input, control| {
550 if u64::from(control.with_code(0)) == 0 && input == 0 && self.is_vtl_call_allowed() {
555 self.advance_ip();
557 self.vtl_call();
558 } else {
559 self.inject_invalid_opcode_fault();
560 }
561 })
562 }
563}
564
565pub trait EnableVpVtl<T> {
567 fn enable_vp_vtl(
569 &mut self,
570 partition_id: u64,
571 vp_index: u32,
572 vtl: Vtl,
573 vp_context: &T,
574 ) -> HvResult<()>;
575}
576
577pub type HvX64EnableVpVtl =
579 SimpleHypercall<defs::EnableVpVtlX64, (), { HypercallCode::HvCallEnableVpVtl.0 }>;
580
581impl<T: EnableVpVtl<hvdef::hypercall::InitialVpContextX64>> HypercallDispatch<HvX64EnableVpVtl>
582 for T
583{
584 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
585 HvX64EnableVpVtl::run(params, |input| {
586 self.enable_vp_vtl(
587 input.partition_id,
588 input.vp_index,
589 Vtl::try_from(input.target_vtl)?,
590 &input.vp_vtl_context,
591 )
592 })
593 }
594}
595
596pub type HvArm64EnableVpVtl =
598 SimpleHypercall<defs::EnableVpVtlArm64, (), { HypercallCode::HvCallEnableVpVtl.0 }>;
599
600impl<T: EnableVpVtl<hvdef::hypercall::InitialVpContextArm64>> HypercallDispatch<HvArm64EnableVpVtl>
601 for T
602{
603 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
604 HvArm64EnableVpVtl::run(params, |input| {
605 self.enable_vp_vtl(
606 input.partition_id,
607 input.vp_index,
608 Vtl::try_from(input.target_vtl)?,
609 &input.vp_vtl_context,
610 )
611 })
612 }
613}
614
615pub trait ModifyVtlProtectionMask {
617 fn modify_vtl_protection_mask(
621 &mut self,
622 partition_id: u64,
623 map_flags: hvdef::HvMapGpaFlags,
624 target_vtl: Option<Vtl>,
625 gpa_pages: &[u64],
626 ) -> HvRepResult;
627}
628
629pub type HvModifyVtlProtectionMask = RepHypercall<
631 defs::ModifyVtlProtectionMask,
632 u64,
633 (),
634 { HypercallCode::HvCallModifyVtlProtectionMask.0 },
635>;
636
637impl<T: ModifyVtlProtectionMask> HypercallDispatch<HvModifyVtlProtectionMask> for T {
638 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
639 HvModifyVtlProtectionMask::run(params, |header, input, _output| {
640 self.modify_vtl_protection_mask(
641 header.partition_id,
642 header.map_flags,
643 header.target_vtl.target_vtl().map_err(|err| (err, 0))?,
644 input,
645 )
646 })
647 }
648}
649
650pub trait GetVpIndexFromApicId {
652 fn get_vp_index_from_apic_id(
654 &mut self,
655 partition_id: u64,
656 target_vtl: Vtl,
657 apic_ids: &[u32],
658 vp_indices: &mut [u32],
659 ) -> HvRepResult;
660}
661
662pub type HvGetVpIndexFromApicId = RepHypercall<
664 defs::GetVpIndexFromApicId,
665 u32,
666 u32,
667 { HypercallCode::HvCallGetVpIndexFromApicId.0 },
668>;
669
670impl<T: GetVpIndexFromApicId> HypercallDispatch<HvGetVpIndexFromApicId> for T {
671 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
672 HvGetVpIndexFromApicId::run(params, |header, input, output| {
673 self.get_vp_index_from_apic_id(
674 header.partition_id,
675 Vtl::try_from(header.target_vtl).map_err(|err| (err, 0))?,
676 input,
677 output,
678 )
679 })
680 }
681}
682
683pub trait AcceptGpaPages {
685 fn accept_gpa_pages(
687 &mut self,
688 partition_id: u64,
689 page_attributes: AcceptPagesAttributes,
690 vtl_permission_set: VtlPermissionSet,
691 gpa_page_base: u64,
692 page_count: usize,
693 ) -> HvRepResult;
694}
695
696pub type HvAcceptGpaPages =
698 RepHypercall<defs::AcceptGpaPages, u64, (), { HypercallCode::HvCallAcceptGpaPages.0 }>;
699
700impl<T: AcceptGpaPages> HypercallDispatch<HvAcceptGpaPages> for T {
701 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
702 HvAcceptGpaPages::run(params, |header, input, _output| {
703 self.accept_gpa_pages(
704 header.partition_id,
705 header.page_attributes,
706 header.vtl_permission_set,
707 header.gpa_page_base,
708 input.len(),
709 )
710 })
711 }
712}
713
714pub trait ModifySparseGpaPageHostVisibility {
716 fn modify_gpa_visibility(
718 &mut self,
719 partition_id: u64,
720 visibility: HostVisibilityType,
721 gpa_pages: &[u64],
722 ) -> HvRepResult;
723}
724
725pub type HvModifySparseGpaPageHostVisibility = RepHypercall<
727 defs::ModifySparsePageVisibility,
728 u64,
729 (),
730 { HypercallCode::HvCallModifySparseGpaPageHostVisibility.0 },
731>;
732
733impl<T: ModifySparseGpaPageHostVisibility> HypercallDispatch<HvModifySparseGpaPageHostVisibility>
734 for T
735{
736 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
737 HvModifySparseGpaPageHostVisibility::run(params, |header, input, _output| {
738 self.modify_gpa_visibility(
739 header.partition_id,
740 header.host_visibility.host_visibility(),
741 input,
742 )
743 })
744 }
745}
746
747pub trait EnablePartitionVtl {
749 fn enable_partition_vtl(
751 &mut self,
752 partition_id: u64,
753 target_vtl: Vtl,
754 flags: defs::EnablePartitionVtlFlags,
755 ) -> HvResult<()>;
756}
757
758pub type HvEnablePartitionVtl =
760 SimpleHypercall<defs::EnablePartitionVtl, (), { HypercallCode::HvCallEnablePartitionVtl.0 }>;
761
762impl<T: EnablePartitionVtl> HypercallDispatch<HvEnablePartitionVtl> for T {
763 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
764 HvEnablePartitionVtl::run(params, |input| {
765 self.enable_partition_vtl(
766 input.partition_id,
767 Vtl::try_from(input.target_vtl).map_err(|_| HvError::AccessDenied)?,
768 input.flags,
769 )
770 })
771 }
772}
773
774pub trait FlushVirtualAddressList {
776 fn flush_virtual_address_list(
778 &mut self,
779 processor_set: ProcessorSet<'_>,
780 flags: defs::HvFlushFlags,
781 gva_ranges: &[defs::HvGvaRange],
782 ) -> HvRepResult;
783}
784
785pub type HvFlushVirtualAddressList = RepHypercall<
787 defs::FlushVirtualAddressSpace,
788 defs::HvGvaRange,
789 (),
790 { HypercallCode::HvCallFlushVirtualAddressList.0 },
791>;
792
793impl<T: FlushVirtualAddressList> HypercallDispatch<HvFlushVirtualAddressList> for T {
794 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
795 HvFlushVirtualAddressList::run(params, |header, input, _output| {
796 let masks = &[header.processor_mask];
797 let processors = ProcessorSet::from_processor_masks(1, masks)
798 .ok_or((HvError::InvalidParameter, 0))?;
799 self.flush_virtual_address_list(processors, header.flags, input)
800 })
801 }
802}
803
804pub trait FlushVirtualAddressListEx {
806 fn flush_virtual_address_list_ex(
808 &mut self,
809 processor_set: ProcessorSet<'_>,
810 flags: defs::HvFlushFlags,
811 gva_ranges: &[defs::HvGvaRange],
812 ) -> HvRepResult;
813}
814
815pub type HvFlushVirtualAddressListEx = VariableRepHypercall<
817 defs::FlushVirtualAddressSpaceEx,
818 defs::HvGvaRange,
819 (),
820 { HypercallCode::HvCallFlushVirtualAddressListEx.0 },
821>;
822
823impl<T: FlushVirtualAddressListEx> HypercallDispatch<HvFlushVirtualAddressListEx> for T {
824 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
825 HvFlushVirtualAddressListEx::run(params, |header, variable_input, input, _output| {
826 if header.vp_set_format != hvdef::hypercall::HV_GENERIC_SET_SPARSE_4K {
827 return Err((HvError::InvalidParameter, 0));
828 }
829
830 let processors =
831 ProcessorSet::from_processor_masks(header.vp_set_valid_banks_mask, variable_input)
832 .ok_or((HvError::InvalidParameter, 0))?;
833 self.flush_virtual_address_list_ex(processors, header.flags, input)
834 })
835 }
836}
837
838pub trait FlushVirtualAddressSpace {
840 fn flush_virtual_address_space(
842 &mut self,
843 processor_set: ProcessorSet<'_>,
844 flags: defs::HvFlushFlags,
845 ) -> HvResult<()>;
846}
847
848pub type HvFlushVirtualAddressSpace = SimpleHypercall<
850 defs::FlushVirtualAddressSpace,
851 (),
852 { HypercallCode::HvCallFlushVirtualAddressSpace.0 },
853>;
854
855impl<T: FlushVirtualAddressSpace> HypercallDispatch<HvFlushVirtualAddressSpace> for T {
856 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
857 HvFlushVirtualAddressSpace::run(params, |input| {
858 let masks = &[input.processor_mask];
859 let processors =
860 ProcessorSet::from_processor_masks(1, masks).ok_or(HvError::InvalidParameter)?;
861 self.flush_virtual_address_space(processors, input.flags)
862 })
863 }
864}
865
866pub trait FlushVirtualAddressSpaceEx {
868 fn flush_virtual_address_space_ex(
870 &mut self,
871 processor_set: ProcessorSet<'_>,
872 flags: defs::HvFlushFlags,
873 ) -> HvResult<()>;
874}
875
876pub type HvFlushVirtualAddressSpaceEx = VariableHypercall<
878 defs::FlushVirtualAddressSpaceEx,
879 (),
880 { HypercallCode::HvCallFlushVirtualAddressSpaceEx.0 },
881>;
882
883impl<T: FlushVirtualAddressSpaceEx> HypercallDispatch<HvFlushVirtualAddressSpaceEx> for T {
884 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
885 HvFlushVirtualAddressSpaceEx::run(params, |header, input| {
886 if header.vp_set_format != hvdef::hypercall::HV_GENERIC_SET_SPARSE_4K {
887 return Err(HvError::InvalidParameter);
888 }
889
890 let processors =
891 ProcessorSet::from_processor_masks(header.vp_set_valid_banks_mask, input)
892 .ok_or(HvError::InvalidParameter)?;
893 self.flush_virtual_address_space_ex(processors, header.flags)
894 })
895 }
896}
897
898pub trait QuerySparseGpaPageHostVisibility {
900 fn query_gpa_visibility(
902 &mut self,
903 partition_id: u64,
904 gpa_pages: &[u64],
905 host_visibility: &mut [HostVisibilityType],
906 ) -> HvRepResult;
907}
908
909pub type HvQuerySparseGpaPageHostVisibility = RepHypercall<
911 defs::QuerySparsePageVisibility,
912 u64,
913 HostVisibilityType,
914 { HypercallCode::HvCallQuerySparseGpaPageHostVisibility.0 },
915>;
916
917impl<T: QuerySparseGpaPageHostVisibility> HypercallDispatch<HvQuerySparseGpaPageHostVisibility>
918 for T
919{
920 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
921 HvQuerySparseGpaPageHostVisibility::run(params, |header, input, output| {
922 self.query_gpa_visibility(header.partition_id, input, output)
923 })
924 }
925}
926
927pub trait ExtendedQueryCapabilities {
929 fn query_extended_capabilities(&mut self) -> HvResult<u64>;
931}
932
933pub type HvExtQueryCapabilities =
935 SimpleHypercall<(), u64, { HypercallCode::HvExtCallQueryCapabilities.0 }>;
936
937impl<T: ExtendedQueryCapabilities> HypercallDispatch<HvExtQueryCapabilities> for T {
938 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
939 HvExtQueryCapabilities::run(params, |()| self.query_extended_capabilities())
940 }
941}
942
943pub type HvSendSyntheticClusterIpi = SimpleHypercall<
945 defs::SendSyntheticClusterIpi,
946 (),
947 { HypercallCode::HvCallSendSyntheticClusterIpi.0 },
948>;
949
950pub trait SendSyntheticClusterIpi {
952 fn send_synthetic_cluster_ipi(
954 &mut self,
955 target_vtl: Option<Vtl>,
956 vector: u32,
957 flags: u8,
958 processor_set: ProcessorSet<'_>,
959 ) -> HvResult<()>;
960}
961
962impl<T: SendSyntheticClusterIpi> HypercallDispatch<HvSendSyntheticClusterIpi> for T {
963 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
964 HvSendSyntheticClusterIpi::run(params, |input| {
965 if input.reserved != 0 {
966 return Err(HvError::InvalidParameter);
967 }
968 self.send_synthetic_cluster_ipi(
969 input.target_vtl.target_vtl()?,
970 input.vector,
971 input.flags,
972 ProcessorSet::from_processor_masks(1, &[input.processor_mask])
973 .ok_or(HvError::InvalidParameter)?,
974 )
975 })
976 }
977}
978
979pub type HvSendSyntheticClusterIpiEx = VariableHypercall<
981 defs::SendSyntheticClusterIpiEx,
982 (),
983 { HypercallCode::HvCallSendSyntheticClusterIpiEx.0 },
984>;
985
986pub trait SendSyntheticClusterIpiEx {
988 fn send_synthetic_cluster_ipi_ex(
990 &mut self,
991 target_vtl: Option<Vtl>,
992 vector: u32,
993 flags: u8,
994 processor_set: ProcessorSet<'_>,
995 ) -> HvResult<()>;
996}
997
998impl<T: SendSyntheticClusterIpiEx> HypercallDispatch<HvSendSyntheticClusterIpiEx> for T {
999 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
1000 HvSendSyntheticClusterIpiEx::run(params, |header, input| {
1001 if header.reserved != 0 {
1002 return Err(HvError::InvalidParameter);
1003 }
1004
1005 if header.vp_set_format != hvdef::hypercall::HV_GENERIC_SET_SPARSE_4K {
1006 return Err(HvError::InvalidParameter);
1007 }
1008
1009 self.send_synthetic_cluster_ipi_ex(
1010 header.target_vtl.target_vtl()?,
1011 header.vector,
1012 header.flags,
1013 ProcessorSet::from_processor_masks(header.vp_set_valid_banks_mask, input)
1014 .ok_or(HvError::InvalidParameter)?,
1015 )
1016 })
1017 }
1018}
1019
1020pub type HvVbsVmCallReport = SimpleHypercall<
1022 defs::VbsVmCallReport,
1023 defs::VbsVmCallReportOutput,
1024 { HypercallCode::HvCallVbsVmCallReport.0 },
1025>;
1026
1027pub trait VbsVmCallReport {
1029 fn vbs_vm_call_report(&self, report_data: &[u8]) -> HvResult<defs::VbsVmCallReportOutput>;
1031}
1032
1033impl<T: VbsVmCallReport> HypercallDispatch<HvVbsVmCallReport> for T {
1034 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
1035 HvVbsVmCallReport::run(params, |header| {
1036 self.vbs_vm_call_report(&header.report_data)
1037 })
1038 }
1039}
1040
1041pub type HvRestorePartitionTime = SimpleHypercall<
1043 defs::RestorePartitionTime,
1044 (),
1045 { HypercallCode::HvCallRestorePartitionTime.0 },
1046>;
1047
1048pub trait RestorePartitionTime {
1050 fn restore_partition_time(
1052 &mut self,
1053 partition_id: u64,
1054 tsc_sequence: u32,
1055 reference_time_in_100_ns: u64,
1056 tsc: u64,
1057 ) -> HvResult<()>;
1058}
1059
1060impl<T: RestorePartitionTime> HypercallDispatch<HvRestorePartitionTime> for T {
1061 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
1062 HvRestorePartitionTime::run(params, |input| {
1063 if input.reserved != 0 {
1064 return Err(HvError::InvalidParameter);
1065 }
1066
1067 self.restore_partition_time(
1068 input.partition_id,
1069 input.tsc_sequence,
1070 input.reference_time_in_100_ns,
1071 input.tsc,
1072 )
1073 })
1074 }
1075}