@@ -785,117 +785,67 @@ pub fn cr_access_info() -> AxResult<CrAccessInfo> {
785785 } )
786786}
787787
788- /// Extract detailed MMIO access information from EPT violation.
788+ /// Extract MMIO access information from EPT violation and return appropriate AxVCpuExitReason .
789789///
790- /// This function provides comprehensive information about MMIO device access
791- /// that triggered an EPT violation, including the access address, width,
792- /// read/write direction, and instruction details.
793- ///
794- /// # Returns
795- /// * `Ok(MmioAccessInfo)` - Detailed MMIO access information
796- /// * `Err(AxError)` - If VMCS read operations fail
797- pub fn mmio_access_info ( ) -> AxResult < MmioAccessInfo > {
798- let qualification = VmcsReadOnlyNW :: EXIT_QUALIFICATION . read ( ) ?;
799- let instruction_info = VmcsReadOnly32 :: VMEXIT_INSTRUCTION_INFO . read ( ) ?;
800- let fault_guest_paddr = VmcsReadOnly64 :: GUEST_PHYSICAL_ADDR . read ( ) ? as usize ;
801-
802- // Extract access type from qualification
803- error ! ( "qualification: {:#x}" , qualification) ;
804- let is_read = qualification. get_bit ( 0 ) ;
805- // Access type is determined by the second bit in the qualification
806- let is_write = qualification. get_bit ( 1 ) ;
807- // Decode instruction information to get access width and register
808-
809- let operand_size = instruction_info. get_bits ( 0 ..3 ) ;
810- let access_width = match operand_size + 1 {
811- 0 => AccessWidth :: Word , // 16-bit
812- 1 => AccessWidth :: Dword , // 32-bit
813- 2 => AccessWidth :: Qword , // 64-bit
814- 3 => AccessWidth :: Byte , // 8-bit
815- _ => AccessWidth :: Dword , // Default to 32-bit for unknown encodings
816- } ;
817-
818- let addr = GuestPhysAddr :: from ( fault_guest_paddr) ;
819- let reg_index: u8 = instruction_info. get_bits ( 7 ..10 ) as u8 ;
820-
821- // For write operations, we need to get the data from guest registers
822- // This will be set by the caller who has access to guest registers
823- let data = if is_write {
824- Some ( 0 as u64 ) // Placeholder - will be filled by caller
825- } else {
826- None
827- } ;
828-
829- Ok ( MmioAccessInfo {
830- addr,
831- access_width,
832- is_read,
833- is_write,
834- register : reg_index,
835- data,
836- } )
837- }
838-
839- /// Extract detailed MMIO access information from EPT violation with guest register data.
840- ///
841- /// This function provides comprehensive information about MMIO device access
842- /// that triggered an EPT violation, including the access address, width,
843- /// read/write direction, instruction details, and actual data for write operations.
790+ /// This function analyzes the EPT violation to determine if it's a MMIO read or write operation,
791+ /// extracts the necessary information, and returns the appropriate exit reason.
844792///
845793/// # Arguments
846794/// * `guest_regs` - Reference to guest general-purpose registers
847795///
848796/// # Returns
849- /// * `Ok(MmioAccessInfo)` - Detailed MMIO access information with actual data
850- /// * `Err(AxError)` - If VMCS read operations fail
851- pub fn mmio_access_info_with_regs ( guest_regs : & crate :: regs:: GeneralRegisters ) -> AxResult < MmioAccessInfo > {
797+ /// * `Ok(AxVCpuExitReason::MmioRead)` - For read operations with addr, width, reg, reg_width
798+ /// * `Ok(AxVCpuExitReason::MmioWrite)` - For write operations with addr, width, data
799+ /// * `Err(AxError)` - If VMCS read operations fail or invalid access type
800+ pub fn mmio_access_exit_reason ( guest_regs : & crate :: regs:: GeneralRegisters ) -> AxResult < axvcpu:: AxVCpuExitReason > {
852801 let qualification = VmcsReadOnlyNW :: EXIT_QUALIFICATION . read ( ) ?;
853802 let instruction_info = VmcsReadOnly32 :: VMEXIT_INSTRUCTION_INFO . read ( ) ?;
854803 let fault_guest_paddr = VmcsReadOnly64 :: GUEST_PHYSICAL_ADDR . read ( ) ? as usize ;
855804
856805 // Extract access type from qualification
857- error ! ( "qualification: {:#x}" , qualification) ;
858806 let is_read = qualification. get_bit ( 0 ) ;
859- // Access type is determined by the second bit in the qualification
860807 let is_write = qualification. get_bit ( 1 ) ;
861- // Decode instruction information to get access width and register
862808
809+ // Decode instruction information to get access width and register
863810 let operand_size = instruction_info. get_bits ( 0 ..3 ) ;
864- let access_width = match operand_size + 1 {
865- 0 => AccessWidth :: Word , // 16 -bit
866- 1 => AccessWidth :: Dword , // 32 -bit
867- 2 => AccessWidth :: Qword , // 64 -bit
868- 3 => AccessWidth :: Byte , // 8 -bit
869- _ => AccessWidth :: Dword , // Default to 32-bit for unknown encodings
811+ let access_width = match operand_size {
812+ 0 => AccessWidth :: Byte , // 8 -bit
813+ 1 => AccessWidth :: Word , // 16 -bit
814+ 2 => AccessWidth :: Dword , // 32 -bit
815+ 3 => AccessWidth :: Qword , // 64 -bit
816+ _ => AccessWidth :: Dword , // Default to 32-bit for unknown encodings
870817 } ;
871818
872819 let addr = GuestPhysAddr :: from ( fault_guest_paddr) ;
873- let reg_index: u8 = instruction_info. get_bits ( 7 ..10 ) as u8 ;
874-
875- // For write operations, get the actual data from the guest register
876- let data = if is_write {
877- // Get the full register value
878- let reg_value = guest_regs. get_reg_of_index ( reg_index) ;
820+ let reg_index = instruction_info. get_bits ( 7 ..10 ) as usize ;
821+
822+ if is_read {
823+ // For read operations, return MmioRead with register information
824+ Ok ( axvcpu:: AxVCpuExitReason :: MmioRead {
825+ addr,
826+ width : access_width,
827+ reg : reg_index,
828+ reg_width : access_width, // Register width same as access width
829+ } )
830+ } else if is_write {
831+ // For write operations, get the data from the guest register
832+ let reg_value = guest_regs. get_reg_of_index ( reg_index as u8 ) ;
879833
880834 // Mask the value based on access width to get only the relevant bits
881- let masked_value = match access_width {
835+ let data = match access_width {
882836 AccessWidth :: Byte => reg_value & 0xFF ,
883837 AccessWidth :: Word => reg_value & 0xFFFF ,
884838 AccessWidth :: Dword => reg_value & 0xFFFFFFFF ,
885839 AccessWidth :: Qword => reg_value,
886840 } ;
887841
888- Some ( masked_value)
842+ Ok ( axvcpu:: AxVCpuExitReason :: MmioWrite {
843+ addr,
844+ width : access_width,
845+ data,
846+ } )
889847 } else {
890- None
891- } ;
892-
893- Ok ( MmioAccessInfo {
894- addr,
895- access_width,
896- is_read,
897- is_write,
898- register : reg_index,
899- data,
900- } )
848+ // Neither read nor write - this shouldn't happen for valid MMIO access
849+ Err ( axerrno:: AxError :: InvalidInput )
850+ }
901851}
0 commit comments