@@ -30,12 +30,14 @@ use mshv_bindings::{
3030 hv_message_type, hv_message_type_HVMSG_GPA_INTERCEPT, hv_message_type_HVMSG_UNMAPPED_GPA,
3131 hv_message_type_HVMSG_X64_HALT, hv_message_type_HVMSG_X64_IO_PORT_INTERCEPT,
3232 hv_partition_property_code_HV_PARTITION_PROPERTY_SYNTHETIC_PROC_FEATURES,
33- hv_partition_synthetic_processor_features, mshv_create_partition_v2, mshv_user_mem_region,
33+ hv_partition_synthetic_processor_features, hv_register_assoc,
34+ hv_register_name_HV_X64_REGISTER_RIP, hv_register_value, mshv_create_partition_v2,
35+ mshv_user_mem_region,
3436} ;
3537#[ cfg( feature = "hw-interrupts" ) ]
3638use mshv_bindings:: {
3739 HV_X64_REGISTER_CLASS_GENERAL , hv_interrupt_type_HV_X64_INTERRUPT_TYPE_FIXED,
38- hv_register_assoc , hv_register_value ,
40+ hv_register_name_HV_X64_REGISTER_RAX , set_gp_regs_field_ptr ,
3941} ;
4042#[ cfg( feature = "hw-interrupts" ) ]
4143use mshv_ioctls:: InterruptRequest ;
@@ -219,19 +221,28 @@ impl VirtualMachine for MshvVm {
219221 let is_write = io_message. header . intercept_access_type != 0 ;
220222
221223 // mshv, unlike kvm, does not automatically increment RIP.
224+ if let Some ( page) = self
225+ . vcpu_fd
226+ . get_vp_reg_page ( )
227+ . filter ( |p| unsafe { ( * p. 0 ) . isvalid != 0 } )
222228 {
223- let page = self
224- . vcpu_fd
225- . get_vp_reg_page ( )
226- . ok_or ( RunVcpuError :: NoVpRegisterPage ) ?;
227- // SAFETY: The register page is a valid mmap'd page
228- // from create_vcpu and is always populated after a
229- // vcpu run returns an intercept message.
229+ // SAFETY: The register page is valid (isvalid checked
230+ // above) and populated after a vcpu run intercept.
230231 unsafe {
231232 ( * page. 0 ) . __bindgen_anon_1 . __bindgen_anon_1 . rip =
232233 rip + instruction_length;
233234 ( * page. 0 ) . dirty |= 1 << HV_X64_REGISTER_CLASS_IP ;
234235 }
236+ } else {
237+ self . vcpu_fd
238+ . set_reg ( & [ hv_register_assoc {
239+ name : hv_register_name_HV_X64_REGISTER_RIP,
240+ value : hv_register_value {
241+ reg64 : rip + instruction_length,
242+ } ,
243+ ..Default :: default ( )
244+ } ] )
245+ . map_err ( |e| RunVcpuError :: IncrementRip ( e. into ( ) ) ) ?;
235246 }
236247
237248 // VmAction::Halt always means "I'm done", regardless
@@ -257,21 +268,26 @@ impl VirtualMachine for MshvVm {
257268 } else if let Some ( val) =
258269 super :: super :: x86_64:: hw_interrupts:: handle_io_in ( port_number)
259270 {
260- let page = self
271+ if let Some ( page) = self
261272 . vcpu_fd
262273 . get_vp_reg_page ( )
263- . ok_or ( RunVcpuError :: NoVpRegisterPage ) ?;
264- // SAFETY: The register page is a valid mmap'd page
265- // from create_vcpu and is always populated after a
266- // vcpu run returns an intercept message.
267- unsafe {
268- ( * page. 0 )
269- . __bindgen_anon_1
270- . __bindgen_anon_1
271- . __bindgen_anon_1
272- . __bindgen_anon_1
273- . rax = val;
274- ( * page. 0 ) . dirty |= 1 << HV_X64_REGISTER_CLASS_GENERAL ;
274+ . filter ( |p| unsafe { ( * p. 0 ) . isvalid != 0 } )
275+ {
276+ let vp_reg_page = page. 0 ;
277+ set_gp_regs_field_ptr ! ( vp_reg_page, rax, val) ;
278+ // SAFETY: page is valid (isvalid checked above).
279+ unsafe {
280+ ( * vp_reg_page) . dirty |=
281+ 1 << HV_X64_REGISTER_CLASS_GENERAL ;
282+ }
283+ } else {
284+ self . vcpu_fd
285+ . set_reg ( & [ hv_register_assoc {
286+ name : hv_register_name_HV_X64_REGISTER_RAX,
287+ value : hv_register_value { reg64 : val } ,
288+ ..Default :: default ( )
289+ } ] )
290+ . map_err ( |e| RunVcpuError :: Unknown ( e. into ( ) ) ) ?;
275291 }
276292 continue ;
277293 }
0 commit comments