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 self.start_virtual_processor(
263 input.partition_id,
264 input.vp_index,
265 Vtl::try_from(input.target_vtl)?,
266 &input.vp_context,
267 )
268 })
269 }
270}
271
272pub type HvArm64StartVirtualProcessor = SimpleHypercall<
274 defs::StartVirtualProcessorArm64,
275 (),
276 { HypercallCode::HvCallStartVirtualProcessor.0 },
277>;
278
279impl<T: StartVirtualProcessor<defs::InitialVpContextArm64>>
280 HypercallDispatch<HvArm64StartVirtualProcessor> for T
281{
282 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
283 HvArm64StartVirtualProcessor::run(params, |input| {
284 self.start_virtual_processor(
285 input.partition_id,
286 input.vp_index,
287 Vtl::try_from(input.target_vtl)?,
288 &input.vp_context,
289 )
290 })
291 }
292}
293
294pub type HvX64TranslateVirtualAddress = SimpleHypercall<
296 defs::TranslateVirtualAddressX64,
297 defs::TranslateVirtualAddressOutput,
298 { HypercallCode::HvCallTranslateVirtualAddress.0 },
299>;
300
301pub trait TranslateVirtualAddressX64 {
303 fn translate_virtual_address(
305 &mut self,
306 partition_id: u64,
307 vp_index: u32,
308 control_flags: defs::TranslateGvaControlFlagsX64,
309 gva_page: u64,
310 ) -> HvResult<defs::TranslateVirtualAddressOutput>;
311}
312
313impl<T: TranslateVirtualAddressX64> HypercallDispatch<HvX64TranslateVirtualAddress> for T {
314 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
315 HvX64TranslateVirtualAddress::run(params, |input| {
316 self.translate_virtual_address(
317 input.partition_id,
318 input.vp_index,
319 input.control_flags,
320 input.gva_page,
321 )
322 })
323 }
324}
325
326pub type HvX64TranslateVirtualAddressEx = SimpleHypercall<
328 defs::TranslateVirtualAddressX64,
329 defs::TranslateVirtualAddressExOutputX64,
330 { HypercallCode::HvCallTranslateVirtualAddressEx.0 },
331>;
332
333pub trait TranslateVirtualAddressExX64 {
335 fn translate_virtual_address_ex(
337 &mut self,
338 partition_id: u64,
339 vp_index: u32,
340 control_flags: defs::TranslateGvaControlFlagsX64,
341 gva_page: u64,
342 ) -> HvResult<defs::TranslateVirtualAddressExOutputX64>;
343}
344
345impl<T: TranslateVirtualAddressExX64> HypercallDispatch<HvX64TranslateVirtualAddressEx> for T {
346 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
347 HvX64TranslateVirtualAddressEx::run(params, |input| {
348 self.translate_virtual_address_ex(
349 input.partition_id,
350 input.vp_index,
351 input.control_flags,
352 input.gva_page,
353 )
354 })
355 }
356}
357
358pub type HvAarch64TranslateVirtualAddressEx = SimpleHypercall<
360 defs::TranslateVirtualAddressArm64,
361 defs::TranslateVirtualAddressExOutputArm64,
362 { HypercallCode::HvCallTranslateVirtualAddressEx.0 },
363>;
364
365pub trait TranslateVirtualAddressExAarch64 {
367 fn translate_virtual_address_ex(
369 &mut self,
370 partition_id: u64,
371 vp_index: u32,
372 control_flags: defs::TranslateGvaControlFlagsArm64,
373 gva_page: u64,
374 ) -> HvResult<defs::TranslateVirtualAddressExOutputArm64>;
375}
376
377impl<T: TranslateVirtualAddressExAarch64> HypercallDispatch<HvAarch64TranslateVirtualAddressEx>
378 for T
379{
380 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
381 HvAarch64TranslateVirtualAddressEx::run(params, |input| {
382 self.translate_virtual_address_ex(
383 input.partition_id,
384 input.vp_index,
385 input.control_flags,
386 input.gva_page,
387 )
388 })
389 }
390}
391
392pub type HvGetVpRegisters = RepHypercall<
394 defs::GetSetVpRegisters,
395 HvRegisterName,
396 HvRegisterValue,
397 { HypercallCode::HvCallGetVpRegisters.0 },
398>;
399
400pub trait GetVpRegisters {
402 fn get_vp_registers(
404 &mut self,
405 partition_id: u64,
406 vp_index: u32,
407 vtl: Option<Vtl>,
408 registers: &[HvRegisterName],
409 output: &mut [HvRegisterValue],
410 ) -> HvRepResult;
411}
412
413impl<T: GetVpRegisters> HypercallDispatch<HvGetVpRegisters> for T {
414 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
415 HvGetVpRegisters::run(params, |header, input, output| {
416 self.get_vp_registers(
417 header.partition_id,
418 header.vp_index,
419 header.target_vtl.target_vtl().map_err(|err| (err, 0))?,
420 input,
421 output,
422 )
423 })
424 }
425}
426
427pub type HvSetVpRegisters = RepHypercall<
429 defs::GetSetVpRegisters,
430 HvRegisterAssoc,
431 (),
432 { HypercallCode::HvCallSetVpRegisters.0 },
433>;
434
435pub trait SetVpRegisters {
437 fn set_vp_registers(
439 &mut self,
440 partition_id: u64,
441 vp_index: u32,
442 vtl: Option<Vtl>,
443 registers: &[HvRegisterAssoc],
444 ) -> HvRepResult;
445}
446
447impl<T: SetVpRegisters> HypercallDispatch<HvSetVpRegisters> for T {
448 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
449 HvSetVpRegisters::run(params, |header, input, _output| {
450 self.set_vp_registers(
451 header.partition_id,
452 header.vp_index,
453 header.target_vtl.target_vtl().map_err(|err| (err, 0))?,
454 input,
455 )
456 })
457 }
458}
459
460pub trait InstallIntercept {
462 fn install_intercept(
464 &mut self,
465 partition_id: u64,
466 access_type_mask: u32,
467 intercept_type: defs::HvInterceptType,
468 intercept_parameters: defs::HvInterceptParameters,
469 ) -> HvResult<()>;
470}
471
472pub type HvInstallIntercept =
474 SimpleHypercall<defs::InstallIntercept, (), { HypercallCode::HvCallInstallIntercept.0 }>;
475
476impl<T: InstallIntercept> HypercallDispatch<HvInstallIntercept> for T {
477 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
478 HvInstallIntercept::run(params, |input| {
479 self.install_intercept(
480 input.partition_id,
481 input.access_type_mask,
482 input.intercept_type,
483 input.intercept_parameters,
484 )
485 })
486 }
487}
488
489pub trait VtlSwitchOps {
491 fn advance_ip(&mut self);
494 fn inject_invalid_opcode_fault(&mut self);
497}
498
499pub trait VtlReturn {
501 fn is_vtl_return_allowed(&self) -> bool;
503
504 fn vtl_return(&mut self, fast: bool);
506}
507
508pub type HvVtlReturn = VtlHypercall<{ HypercallCode::HvCallVtlReturn.0 }>;
510
511impl<T: VtlReturn + VtlSwitchOps> HypercallDispatch<HvVtlReturn> for T {
512 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
513 HvVtlReturn::run(params, |input, control| {
514 if u64::from(control.with_code(0)) == 0
519 && (input & !1) == 0
520 && self.is_vtl_return_allowed()
521 {
522 self.advance_ip();
524 self.vtl_return(input & 1 != 0);
525 } else {
526 self.inject_invalid_opcode_fault();
528 }
529 })
530 }
531}
532
533pub trait VtlCall {
535 fn is_vtl_call_allowed(&self) -> bool;
537 fn vtl_call(&mut self);
539}
540
541pub type HvVtlCall = VtlHypercall<{ HypercallCode::HvCallVtlCall.0 }>;
543
544impl<T: VtlCall + VtlSwitchOps> HypercallDispatch<HvVtlCall> for T {
545 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
546 HvVtlCall::run(params, |input, control| {
547 if u64::from(control.with_code(0)) == 0 && input == 0 && self.is_vtl_call_allowed() {
552 self.advance_ip();
554 self.vtl_call();
555 } else {
556 self.inject_invalid_opcode_fault();
557 }
558 })
559 }
560}
561
562pub trait EnableVpVtl<T> {
564 fn enable_vp_vtl(
566 &mut self,
567 partition_id: u64,
568 vp_index: u32,
569 vtl: Vtl,
570 vp_context: &T,
571 ) -> HvResult<()>;
572}
573
574pub type HvX64EnableVpVtl =
576 SimpleHypercall<defs::EnableVpVtlX64, (), { HypercallCode::HvCallEnableVpVtl.0 }>;
577
578impl<T: EnableVpVtl<hvdef::hypercall::InitialVpContextX64>> HypercallDispatch<HvX64EnableVpVtl>
579 for T
580{
581 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
582 HvX64EnableVpVtl::run(params, |input| {
583 self.enable_vp_vtl(
584 input.partition_id,
585 input.vp_index,
586 Vtl::try_from(input.target_vtl)?,
587 &input.vp_vtl_context,
588 )
589 })
590 }
591}
592
593pub type HvArm64EnableVpVtl =
595 SimpleHypercall<defs::EnableVpVtlArm64, (), { HypercallCode::HvCallEnableVpVtl.0 }>;
596
597impl<T: EnableVpVtl<hvdef::hypercall::InitialVpContextArm64>> HypercallDispatch<HvArm64EnableVpVtl>
598 for T
599{
600 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
601 HvArm64EnableVpVtl::run(params, |input| {
602 self.enable_vp_vtl(
603 input.partition_id,
604 input.vp_index,
605 Vtl::try_from(input.target_vtl)?,
606 &input.vp_vtl_context,
607 )
608 })
609 }
610}
611
612pub trait ModifyVtlProtectionMask {
614 fn modify_vtl_protection_mask(
618 &mut self,
619 partition_id: u64,
620 map_flags: hvdef::HvMapGpaFlags,
621 target_vtl: Option<Vtl>,
622 gpa_pages: &[u64],
623 ) -> HvRepResult;
624}
625
626pub type HvModifyVtlProtectionMask = RepHypercall<
628 defs::ModifyVtlProtectionMask,
629 u64,
630 (),
631 { HypercallCode::HvCallModifyVtlProtectionMask.0 },
632>;
633
634impl<T: ModifyVtlProtectionMask> HypercallDispatch<HvModifyVtlProtectionMask> for T {
635 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
636 HvModifyVtlProtectionMask::run(params, |header, input, _output| {
637 self.modify_vtl_protection_mask(
638 header.partition_id,
639 header.map_flags,
640 header.target_vtl.target_vtl().map_err(|err| (err, 0))?,
641 input,
642 )
643 })
644 }
645}
646
647pub trait GetVpIndexFromApicId {
649 fn get_vp_index_from_apic_id(
651 &mut self,
652 partition_id: u64,
653 target_vtl: Vtl,
654 apic_ids: &[u32],
655 vp_indices: &mut [u32],
656 ) -> HvRepResult;
657}
658
659pub type HvGetVpIndexFromApicId = RepHypercall<
661 defs::GetVpIndexFromApicId,
662 u32,
663 u32,
664 { HypercallCode::HvCallGetVpIndexFromApicId.0 },
665>;
666
667impl<T: GetVpIndexFromApicId> HypercallDispatch<HvGetVpIndexFromApicId> for T {
668 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
669 HvGetVpIndexFromApicId::run(params, |header, input, output| {
670 self.get_vp_index_from_apic_id(
671 header.partition_id,
672 Vtl::try_from(header.target_vtl).map_err(|err| (err, 0))?,
673 input,
674 output,
675 )
676 })
677 }
678}
679
680pub trait AcceptGpaPages {
682 fn accept_gpa_pages(
684 &mut self,
685 partition_id: u64,
686 page_attributes: AcceptPagesAttributes,
687 vtl_permission_set: VtlPermissionSet,
688 gpa_page_base: u64,
689 page_count: usize,
690 ) -> HvRepResult;
691}
692
693pub type HvAcceptGpaPages =
695 RepHypercall<defs::AcceptGpaPages, u64, (), { HypercallCode::HvCallAcceptGpaPages.0 }>;
696
697impl<T: AcceptGpaPages> HypercallDispatch<HvAcceptGpaPages> for T {
698 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
699 HvAcceptGpaPages::run(params, |header, input, _output| {
700 self.accept_gpa_pages(
701 header.partition_id,
702 header.page_attributes,
703 header.vtl_permission_set,
704 header.gpa_page_base,
705 input.len(),
706 )
707 })
708 }
709}
710
711pub trait ModifySparseGpaPageHostVisibility {
713 fn modify_gpa_visibility(
715 &mut self,
716 partition_id: u64,
717 visibility: HostVisibilityType,
718 gpa_pages: &[u64],
719 ) -> HvRepResult;
720}
721
722pub type HvModifySparseGpaPageHostVisibility = RepHypercall<
724 defs::ModifySparsePageVisibility,
725 u64,
726 (),
727 { HypercallCode::HvCallModifySparseGpaPageHostVisibility.0 },
728>;
729
730impl<T: ModifySparseGpaPageHostVisibility> HypercallDispatch<HvModifySparseGpaPageHostVisibility>
731 for T
732{
733 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
734 HvModifySparseGpaPageHostVisibility::run(params, |header, input, _output| {
735 self.modify_gpa_visibility(
736 header.partition_id,
737 header.host_visibility.host_visibility(),
738 input,
739 )
740 })
741 }
742}
743
744pub trait EnablePartitionVtl {
746 fn enable_partition_vtl(
748 &mut self,
749 partition_id: u64,
750 target_vtl: Vtl,
751 flags: defs::EnablePartitionVtlFlags,
752 ) -> HvResult<()>;
753}
754
755pub type HvEnablePartitionVtl =
757 SimpleHypercall<defs::EnablePartitionVtl, (), { HypercallCode::HvCallEnablePartitionVtl.0 }>;
758
759impl<T: EnablePartitionVtl> HypercallDispatch<HvEnablePartitionVtl> for T {
760 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
761 HvEnablePartitionVtl::run(params, |input| {
762 self.enable_partition_vtl(
763 input.partition_id,
764 Vtl::try_from(input.target_vtl).map_err(|_| HvError::AccessDenied)?,
765 input.flags,
766 )
767 })
768 }
769}
770
771pub trait FlushVirtualAddressList {
773 fn flush_virtual_address_list(
775 &mut self,
776 processor_set: ProcessorSet<'_>,
777 flags: defs::HvFlushFlags,
778 gva_ranges: &[defs::HvGvaRange],
779 ) -> HvRepResult;
780}
781
782pub type HvFlushVirtualAddressList = RepHypercall<
784 defs::FlushVirtualAddressSpace,
785 defs::HvGvaRange,
786 (),
787 { HypercallCode::HvCallFlushVirtualAddressList.0 },
788>;
789
790impl<T: FlushVirtualAddressList> HypercallDispatch<HvFlushVirtualAddressList> for T {
791 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
792 HvFlushVirtualAddressList::run(params, |header, input, _output| {
793 let masks = &[header.processor_mask];
794 let processors = ProcessorSet::from_processor_masks(1, masks)
795 .ok_or((HvError::InvalidParameter, 0))?;
796 self.flush_virtual_address_list(processors, header.flags, input)
797 })
798 }
799}
800
801pub trait FlushVirtualAddressListEx {
803 fn flush_virtual_address_list_ex(
805 &mut self,
806 processor_set: ProcessorSet<'_>,
807 flags: defs::HvFlushFlags,
808 gva_ranges: &[defs::HvGvaRange],
809 ) -> HvRepResult;
810}
811
812pub type HvFlushVirtualAddressListEx = VariableRepHypercall<
814 defs::FlushVirtualAddressSpaceEx,
815 defs::HvGvaRange,
816 (),
817 { HypercallCode::HvCallFlushVirtualAddressListEx.0 },
818>;
819
820impl<T: FlushVirtualAddressListEx> HypercallDispatch<HvFlushVirtualAddressListEx> for T {
821 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
822 HvFlushVirtualAddressListEx::run(params, |header, variable_input, input, _output| {
823 if header.vp_set_format != hvdef::hypercall::HV_GENERIC_SET_SPARSE_4K {
824 return Err((HvError::InvalidParameter, 0));
825 }
826
827 let processors =
828 ProcessorSet::from_processor_masks(header.vp_set_valid_banks_mask, variable_input)
829 .ok_or((HvError::InvalidParameter, 0))?;
830 self.flush_virtual_address_list_ex(processors, header.flags, input)
831 })
832 }
833}
834
835pub trait FlushVirtualAddressSpace {
837 fn flush_virtual_address_space(
839 &mut self,
840 processor_set: ProcessorSet<'_>,
841 flags: defs::HvFlushFlags,
842 ) -> HvResult<()>;
843}
844
845pub type HvFlushVirtualAddressSpace = SimpleHypercall<
847 defs::FlushVirtualAddressSpace,
848 (),
849 { HypercallCode::HvCallFlushVirtualAddressSpace.0 },
850>;
851
852impl<T: FlushVirtualAddressSpace> HypercallDispatch<HvFlushVirtualAddressSpace> for T {
853 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
854 HvFlushVirtualAddressSpace::run(params, |input| {
855 let masks = &[input.processor_mask];
856 let processors =
857 ProcessorSet::from_processor_masks(1, masks).ok_or(HvError::InvalidParameter)?;
858 self.flush_virtual_address_space(processors, input.flags)
859 })
860 }
861}
862
863pub trait FlushVirtualAddressSpaceEx {
865 fn flush_virtual_address_space_ex(
867 &mut self,
868 processor_set: ProcessorSet<'_>,
869 flags: defs::HvFlushFlags,
870 ) -> HvResult<()>;
871}
872
873pub type HvFlushVirtualAddressSpaceEx = VariableHypercall<
875 defs::FlushVirtualAddressSpaceEx,
876 (),
877 { HypercallCode::HvCallFlushVirtualAddressSpaceEx.0 },
878>;
879
880impl<T: FlushVirtualAddressSpaceEx> HypercallDispatch<HvFlushVirtualAddressSpaceEx> for T {
881 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
882 HvFlushVirtualAddressSpaceEx::run(params, |header, input| {
883 if header.vp_set_format != hvdef::hypercall::HV_GENERIC_SET_SPARSE_4K {
884 return Err(HvError::InvalidParameter);
885 }
886
887 let processors =
888 ProcessorSet::from_processor_masks(header.vp_set_valid_banks_mask, input)
889 .ok_or(HvError::InvalidParameter)?;
890 self.flush_virtual_address_space_ex(processors, header.flags)
891 })
892 }
893}
894
895pub trait QuerySparseGpaPageHostVisibility {
897 fn query_gpa_visibility(
899 &mut self,
900 partition_id: u64,
901 gpa_pages: &[u64],
902 host_visibility: &mut [HostVisibilityType],
903 ) -> HvRepResult;
904}
905
906pub type HvQuerySparseGpaPageHostVisibility = RepHypercall<
908 defs::QuerySparsePageVisibility,
909 u64,
910 HostVisibilityType,
911 { HypercallCode::HvCallQuerySparseGpaPageHostVisibility.0 },
912>;
913
914impl<T: QuerySparseGpaPageHostVisibility> HypercallDispatch<HvQuerySparseGpaPageHostVisibility>
915 for T
916{
917 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
918 HvQuerySparseGpaPageHostVisibility::run(params, |header, input, output| {
919 self.query_gpa_visibility(header.partition_id, input, output)
920 })
921 }
922}
923
924pub trait ExtendedQueryCapabilities {
926 fn query_extended_capabilities(&mut self) -> HvResult<u64>;
928}
929
930pub type HvExtQueryCapabilities =
932 SimpleHypercall<(), u64, { HypercallCode::HvExtCallQueryCapabilities.0 }>;
933
934impl<T: ExtendedQueryCapabilities> HypercallDispatch<HvExtQueryCapabilities> for T {
935 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
936 HvExtQueryCapabilities::run(params, |()| self.query_extended_capabilities())
937 }
938}
939
940pub type HvSendSyntheticClusterIpi = SimpleHypercall<
942 defs::SendSyntheticClusterIpi,
943 (),
944 { HypercallCode::HvCallSendSyntheticClusterIpi.0 },
945>;
946
947pub trait SendSyntheticClusterIpi {
949 fn send_synthetic_cluster_ipi(
951 &mut self,
952 target_vtl: Option<Vtl>,
953 vector: u32,
954 flags: u8,
955 processor_set: ProcessorSet<'_>,
956 ) -> HvResult<()>;
957}
958
959impl<T: SendSyntheticClusterIpi> HypercallDispatch<HvSendSyntheticClusterIpi> for T {
960 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
961 HvSendSyntheticClusterIpi::run(params, |input| {
962 if input.reserved != 0 {
963 return Err(HvError::InvalidParameter);
964 }
965 self.send_synthetic_cluster_ipi(
966 input.target_vtl.target_vtl()?,
967 input.vector,
968 input.flags,
969 ProcessorSet::from_processor_masks(1, &[input.processor_mask])
970 .ok_or(HvError::InvalidParameter)?,
971 )
972 })
973 }
974}
975
976pub type HvSendSyntheticClusterIpiEx = VariableHypercall<
978 defs::SendSyntheticClusterIpiEx,
979 (),
980 { HypercallCode::HvCallSendSyntheticClusterIpiEx.0 },
981>;
982
983pub trait SendSyntheticClusterIpiEx {
985 fn send_synthetic_cluster_ipi_ex(
987 &mut self,
988 target_vtl: Option<Vtl>,
989 vector: u32,
990 flags: u8,
991 processor_set: ProcessorSet<'_>,
992 ) -> HvResult<()>;
993}
994
995impl<T: SendSyntheticClusterIpiEx> HypercallDispatch<HvSendSyntheticClusterIpiEx> for T {
996 fn dispatch(&mut self, params: HypercallParameters<'_>) -> HypercallOutput {
997 HvSendSyntheticClusterIpiEx::run(params, |header, input| {
998 if header.reserved != 0 {
999 return Err(HvError::InvalidParameter);
1000 }
1001
1002 if header.vp_set_format != hvdef::hypercall::HV_GENERIC_SET_SPARSE_4K {
1003 return Err(HvError::InvalidParameter);
1004 }
1005
1006 self.send_synthetic_cluster_ipi_ex(
1007 header.target_vtl.target_vtl()?,
1008 header.vector,
1009 header.flags,
1010 ProcessorSet::from_processor_masks(header.vp_set_valid_banks_mask, input)
1011 .ok_or(HvError::InvalidParameter)?,
1012 )
1013 })
1014 }
1015}