diff --git a/amdsmi_cli/amdsmi_helpers.py b/amdsmi_cli/amdsmi_helpers.py index 9c43c4f024..a846f8e84d 100644 --- a/amdsmi_cli/amdsmi_helpers.py +++ b/amdsmi_cli/amdsmi_helpers.py @@ -57,6 +57,7 @@ class AMDSMIHelpers(): self._is_windows = False self._count_of_sets_called = 0 + # Check if the system is a virtual OS if self.operating_system.startswith("Linux"): self._is_linux = True logging.debug(f"AMDSMIHelpers: Platform is linux:{self._is_linux}") @@ -70,14 +71,27 @@ class AMDSMIHelpers(): self._is_baremetal = not self._is_virtual_os - # Check for passthrough system filtering by device id + if self._is_virtual_os: + #If hard coded passthrough device ids exist on Virtual OS, + # then it is a passthrough system output = self.get_pci_device_ids() passthrough_device_ids = ["7460", "73c8", "74a0", "74a1", "74a2"] if any(('0x' + device_id) in output for device_id in passthrough_device_ids): - if self._is_virtual_os: - self._is_baremetal = True - self._is_virtual_os = False - self._is_passthrough = True + self._is_baremetal = True + self._is_virtual_os = False + self._is_passthrough = True + + # Check for passthrough system dynamically via drm querying id_flags + if self.is_amdgpu_initialized() and not self._is_passthrough: + device_handles = amdsmi_interface.amdsmi_get_processor_handles() + for dev in device_handles: + passthrough_info = amdsmi_interface.amdsmi_get_gpu_passthrough_info(dev) + # isolate the relevant bits and then shift them over to get the correct values + ids_flags = (passthrough_info['ids_flags'] & amdsmi_interface.AmdSmiPassthroughInfoFlags.MASK) >> amdsmi_interface.AmdSmiPassthroughInfoFlags.SHIFT + if ids_flags & amdsmi_interface.AmdSmiPassthroughInfoFlags.PT == 0x2: + self._is_baremetal = True + self._is_virtual_os = False + self._is_passthrough = True def increment_set_count(self): self._count_of_sets_called += 1 @@ -693,7 +707,7 @@ class AMDSMIHelpers(): accelerator_partition_profiles['profile_indices'].append(str(profile['profiles'][p]['profile_index'])) accelerator_partition_profiles['profile_types'].append(profile['profiles'][p]['profile_type']) accelerator_partition_profiles['memory_caps'].append(profile['profiles'][p]['memory_caps']) - break # Only need to get the profiles for one device + break # Only need to get the profiles for one device except amdsmi_interface.AmdSmiLibraryException as e: break return accelerator_partition_profiles diff --git a/include/amd_smi/amdsmi.h b/include/amd_smi/amdsmi.h index e583c041d1..e6a6da0f60 100644 --- a/include/amd_smi/amdsmi.h +++ b/include/amd_smi/amdsmi.h @@ -1680,6 +1680,17 @@ typedef struct { uint64_t reserved[15]; } amdsmi_topology_nearest_t; + +/** + * @brief This structure contains information about passthrough mode in guest systems. + */ +typedef struct { + uint32_t device_id; + uint32_t rev_id; + uint32_t vendor_id; + uint64_t ids_flags; +} amdsmi_passthrough_info_t; + //! Place-holder "variant" for functions that have don't have any variants, //! but do have monitors or sensors. #define AMDSMI_DEFAULT_VARIANT 0xFFFFFFFFFFFFFFFF @@ -5321,6 +5332,10 @@ amdsmi_get_link_topology_nearest(amdsmi_processor_handle processor_handle, amdsmi_link_type_t link_type, amdsmi_topology_nearest_t* topology_nearest_info); +amdsmi_status_t +amdsmi_get_gpu_passthrough_info(amdsmi_processor_handle processor_handle, + amdsmi_passthrough_info_t* info); + #ifdef ENABLE_ESMI_LIB /*****************************************************************************/ /** @defgroup energyinfo Energy information (RAPL MSR) diff --git a/include/amd_smi/impl/amdgpu_drm.h b/include/amd_smi/impl/amdgpu_drm.h index aa88e2f53c..fe896de726 100644 --- a/include/amd_smi/impl/amdgpu_drm.h +++ b/include/amd_smi/impl/amdgpu_drm.h @@ -730,6 +730,18 @@ struct drm_amdgpu_cs_chunk_data { */ #define AMDGPU_IDS_FLAGS_FUSION 0x1 #define AMDGPU_IDS_FLAGS_PREEMPTION 0x2 +#define AMDGPU_IDS_FLAGS_TMZ 0x4 +#define AMDGPU_IDS_FLAGS_CONFORMANT_TRUNC_COORD 0x8 + +/* + * Query h/w info: Flag identifying VF/PF/PT mode + * + */ +#define AMDGPU_IDS_FLAGS_MODE_MASK 0x300 +#define AMDGPU_IDS_FLAGS_MODE_SHIFT 0x8 +#define AMDGPU_IDS_FLAGS_MODE_PF 0x0 +#define AMDGPU_IDS_FLAGS_MODE_VF 0x1 +#define AMDGPU_IDS_FLAGS_MODE_PT 0x2 /* indicate if acceleration can be working */ #define AMDGPU_INFO_ACCEL_WORKING 0x00 @@ -1059,7 +1071,7 @@ struct drm_amdgpu_info_device { __u32 num_rb_pipes; __u32 num_hw_gfx_contexts; __u32 _pad; - __u64 ids_flags; + __u64 ids_flags; // Relevant info here REMOVE LATER /** Starting virtual address for UMDs. */ __u64 virtual_address_offset; /** The maximum virtual address */ diff --git a/py-interface/amdsmi_interface.py b/py-interface/amdsmi_interface.py index 680857bf2b..25230aba2f 100644 --- a/py-interface/amdsmi_interface.py +++ b/py-interface/amdsmi_interface.py @@ -438,6 +438,13 @@ class AmdSmiRegType(IntEnum): USR1 = amdsmi_wrapper.AMDSMI_REG_USR1 +class AmdSmiPassthroughInfoFlags(IntEnum): + MASK = 0x300 + SHIFT = 0x8 + PF = 0x0 + VT = 0x1 + PT = 0x2 + class AmdSmiEventReader: def __init__( self, processor_handle: amdsmi_wrapper.amdsmi_processor_handle, @@ -4458,3 +4465,25 @@ def amdsmi_get_link_topology_nearest( return { 'processor_list': device_list } + +def amdsmi_get_gpu_passthrough_info( + processor_handle: amdsmi_wrapper.amdsmi_processor_handle + ) -> Dict[str, int]: + + # make info struct here + info = amdsmi_wrapper.amdsmi_passthrough_info_t() + + # call lib function here + _check_res( + amdsmi_wrapper.amdsmi_get_gpu_passthrough_info( + processor_handle, + ctypes.byref(info) + ) + ) + + return { + "device_id": info.device_id, + "rev_id": info.rev_id, + "vendor_id": info.vendor_id, + "ids_flags": info.ids_flags + } diff --git a/py-interface/amdsmi_wrapper.py b/py-interface/amdsmi_wrapper.py index 2256c4bf25..6dbdc0d8cf 100644 --- a/py-interface/amdsmi_wrapper.py +++ b/py-interface/amdsmi_wrapper.py @@ -1989,6 +1989,21 @@ struct_amdsmi_topology_nearest_t._fields_ = [ ] amdsmi_topology_nearest_t = struct_amdsmi_topology_nearest_t + +class struct_amdsmi_passthrough_info_t(Structure): + pass + +struct_amdsmi_passthrough_info_t._pack_ = 1 # source:False +struct_amdsmi_passthrough_info_t._fields_ = [ + ('device_id', ctypes.c_uint32), + ('rev_id', ctypes.c_uint32), + ('vendor_id', ctypes.c_uint32), + ('PADDING_0', ctypes.c_ubyte * 4), + ('ids_flags', ctypes.c_uint64), +] + +amdsmi_passthrough_info_t = struct_amdsmi_passthrough_info_t + class struct_amdsmi_hsmp_driver_version_t(Structure): pass @@ -1999,6 +2014,7 @@ struct_amdsmi_hsmp_driver_version_t._fields_ = [ ] amdsmi_hsmp_driver_version_t = struct_amdsmi_hsmp_driver_version_t + class struct_amdsmi_smu_fw_version_t(Structure): pass @@ -2554,6 +2570,9 @@ amdsmi_get_gpu_total_ecc_count.argtypes = [amdsmi_processor_handle, ctypes.POINT amdsmi_get_link_topology_nearest = _libraries['libamd_smi.so'].amdsmi_get_link_topology_nearest amdsmi_get_link_topology_nearest.restype = amdsmi_status_t amdsmi_get_link_topology_nearest.argtypes = [amdsmi_processor_handle, amdsmi_link_type_t, ctypes.POINTER(struct_amdsmi_topology_nearest_t)] +amdsmi_get_gpu_passthrough_info = _libraries['libamd_smi.so'].amdsmi_get_gpu_passthrough_info +amdsmi_get_gpu_passthrough_info.restype = amdsmi_status_t +amdsmi_get_gpu_passthrough_info.argtypes = [amdsmi_processor_handle, ctypes.POINTER(struct_amdsmi_passthrough_info_t)] amdsmi_get_cpu_core_energy = _libraries['libamd_smi.so'].amdsmi_get_cpu_core_energy amdsmi_get_cpu_core_energy.restype = amdsmi_status_t amdsmi_get_cpu_core_energy.argtypes = [amdsmi_processor_handle, ctypes.POINTER(ctypes.c_uint64)] @@ -2976,7 +2995,7 @@ __all__ = \ 'amdsmi_get_gpu_metrics_info', 'amdsmi_get_gpu_od_volt_curve_regions', 'amdsmi_get_gpu_od_volt_info', 'amdsmi_get_gpu_overdrive_level', - 'amdsmi_get_gpu_pci_bandwidth', + 'amdsmi_get_gpu_passthrough_info', 'amdsmi_get_gpu_pci_bandwidth', 'amdsmi_get_gpu_pci_replay_counter', 'amdsmi_get_gpu_pci_throughput', 'amdsmi_get_gpu_perf_level', 'amdsmi_get_gpu_pm_metrics_info', @@ -3025,9 +3044,9 @@ __all__ = \ 'amdsmi_mm_ip_t', 'amdsmi_name_value_t', 'amdsmi_nps_caps_t', 'amdsmi_od_vddc_point_t', 'amdsmi_od_volt_curve_t', 'amdsmi_od_volt_freq_data_t', 'amdsmi_p2p_capability_t', - 'amdsmi_pcie_bandwidth_t', 'amdsmi_pcie_info_t', - 'amdsmi_power_cap_info_t', 'amdsmi_power_info_t', - 'amdsmi_power_profile_preset_masks_t', + 'amdsmi_passthrough_info_t', 'amdsmi_pcie_bandwidth_t', + 'amdsmi_pcie_info_t', 'amdsmi_power_cap_info_t', + 'amdsmi_power_info_t', 'amdsmi_power_profile_preset_masks_t', 'amdsmi_power_profile_status_t', 'amdsmi_proc_info_t', 'amdsmi_process_handle_t', 'amdsmi_process_info_t', 'amdsmi_processor_handle', 'amdsmi_range_t', @@ -3093,6 +3112,7 @@ __all__ = \ 'struct_amdsmi_od_volt_curve_t', 'struct_amdsmi_od_volt_freq_data_t', 'struct_amdsmi_p2p_capability_t', + 'struct_amdsmi_passthrough_info_t', 'struct_amdsmi_pcie_bandwidth_t', 'struct_amdsmi_pcie_info_t', 'struct_amdsmi_power_cap_info_t', 'struct_amdsmi_power_info_t', 'struct_amdsmi_power_profile_status_t', diff --git a/src/amd_smi/amd_smi.cc b/src/amd_smi/amd_smi.cc index ef9897410c..e23313a8d9 100644 --- a/src/amd_smi/amd_smi.cc +++ b/src/amd_smi/amd_smi.cc @@ -3785,6 +3785,42 @@ amdsmi_get_link_topology_nearest(amdsmi_processor_handle processor_handle, return status; } +amdsmi_status_t +amdsmi_get_gpu_passthrough_info(amdsmi_processor_handle processor_handle, amdsmi_passthrough_info_t *info) { + + AMDSMI_CHECK_INIT(); + + if (info == nullptr) { + return AMDSMI_STATUS_INVAL; + } + + struct drm_amdgpu_info_device dev_info = {}; + + amd::smi::AMDSmiGPUDevice* gpu_device = nullptr; + amdsmi_status_t r = get_gpu_device_from_handle(processor_handle, &gpu_device); + if (r != AMDSMI_STATUS_SUCCESS) + return r; + + amdsmi_status_t status; + if (gpu_device->check_if_drm_is_supported()){ + status = gpu_device->amdgpu_query_info(AMDGPU_INFO_DEV_INFO, sizeof(struct drm_amdgpu_info_device), &dev_info); + if (status != AMDSMI_STATUS_SUCCESS) return status; + + SMIGPUDEVICE_MUTEX(gpu_device->get_mutex()) + + info->device_id = dev_info.device_id; + info->rev_id = dev_info.pci_rev; + info->vendor_id = gpu_device->get_vendor_id(); + info->ids_flags = dev_info.ids_flags; + } + else { + return AMDSMI_STATUS_DRM_ERROR; + } + + return AMDSMI_STATUS_SUCCESS; +} + + #ifdef ENABLE_ESMI_LIB static amdsmi_status_t amdsmi_errno_to_esmi_status(amdsmi_status_t status) {