diff --git a/CHANGELOG.md b/CHANGELOG.md index dec23bb3c0..d8c59176fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,308 @@ Full documentation for amd_smi_lib is available at [https://rocm.docs.amd.com/projects/amdsmi](https://rocm.docs.amd.com/projects/amdsmi/en/latest/). ***All information listed below is for reference and subject to change.*** +## amd_smi_lib for ROCm 6.4.0 + +### Added + +- **Added fclk and socclk info to `amd-smi metric -c/--clock`**. + fclk and socclk information such as min and max clock have been added to the metric command, in line with all the other clocks. + + ```shell + amd-smi metric -c -g 1 + ... + FCLK_0: + CLK: 2301 MHz + MIN_CLK: 601 MHz + MAX_CLK: 2301 MHz + CLK_LOCKED: N/A + DEEP_SLEEP: DISABLED + SOCCLK_0: + CLK: 1500 MHz + MIN_CLK: 500 MHz + MAX_CLK: 1500 MHz + CLK_LOCKED: N/A + DEEP_SLEEP: DISABLED + ``` + +- **Added new command `amd-smi set -c/--clock-level`**. + This new command sets the performance level of the selected clock on the desired GPUs. The command can accept a range of acceptable levels, but will not set the level when a level is beyond the number of frequency levels as show in `amd-smi static -C/--clock`. + +```shell +sudo amd-smi set -c sclk 5 6 +GPU: 0 + CLK_LEVEL: Successfully changed sclk perf level(s) to 5, 6 + +GPU: 1 + CLK_LEVEL: level(s) 5, 6 is/are greater than performance levels supported for device +``` + +- **Added new command `amd-smi static -C/--clock`**. + This new command displays the clock frequency performance levels for the selected GPUs and clocks. + +```shell +amd-smi static --clock all -g 0 +GPU: 0 + CLOCK: + SYS: + CURRENT LEVEL: 2 + FREQUENCY_LEVELS: + 0: 300 MHz + 1: 904 MHz + 2: 1165 MHz + 3: 1360 MHz + 4: 1440 MHz + 5: 1544 MHz + 6: 1627 MHz + 7: 1720 MHz + 8: 1800 MHz + MEM: + CURRENT LEVEL: 0 + FREQUENCY_LEVELS: + 0: 167 MHz + DF: + CURRENT LEVEL: 0 + FREQUENCY_LEVELS: + 0: 1400 MHz + SOC: + CURRENT LEVEL: 0 + FREQUENCY_LEVELS: + 0: 302 MHz + DCEF: N/A + VCLK0: N/A + VCLK1: N/A + DCLK0: N/A + DCLK1: N/A +``` + +## amd_smi_lib for ROCm 6.4.0 + +### Added + +### Changed + +### Removed + +- **Removed `GFX_BUSY_ACC` from `amd-smi metric --usage`**. + Displaying `GFX_BUSY_ACC` does not provide helpful outputs for users. + + Old output: + ```shell + $ amd-smi metric --usage + GPU: 0 + USAGE: + GFX_ACTIVITY: 0 % + UMC_ACTIVITY: 0 % + MM_ACTIVITY: N/A + VCN_ACTIVITY: [0 %, 0 %, 0 %, 0 %] + JPEG_ACTIVITY: [0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %] + GFX_BUSY_INST: + XCP_0: [0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %] + JPEG_BUSY: + XCP_0: [0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %] + VCN_BUSY: + XCP_0: [0 %, 0 %, 0 %, 0 %] + GFX_BUSY_ACC: + XCP_0: [N/A, N/A, N/A, N/A, N/A, N/A, N/A, N/A] + ... + ``` + + New Output: + ```shell + $ amd-smi metric --usage + GPU: 0 + USAGE: + GFX_ACTIVITY: 0 % + UMC_ACTIVITY: 0 % + MM_ACTIVITY: N/A + VCN_ACTIVITY: [0 %, 0 %, 0 %, 0 %] + JPEG_ACTIVITY: [0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %] + GFX_BUSY_INST: + XCP_0: [0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %] + JPEG_BUSY: + XCP_0: [0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %] + VCN_BUSY: + XCP_0: [0 %, 0 %, 0 %, 0 %] + ... + ``` + + +### Optimized + +- **Modified `amd-smi` CLI to allow case insensitive arguments if the argument does not begin with a single dash**. + - With this change `amd-smi version` and `amd-smi VERSION` will now yield the same output. + - `amd-smi static --bus` and `amd-smi STATIC --BUS` will produce identical results. + - `amd-smi static -b` and `amd-smi static -B` will still return different results (-b for bus and -B for board). + +- **Converted xgmi read and write from KB's to readable units**. + - With this change `amd-smi xgmi` will now display the statistics in dynamically selected readable units. + - Example output is shown below. + +```shell +$ amd-smi xgmi +LINK METRIC TABLE: + bdf bit_rate max_bandwidth link_type 0000:05:00.0 0000:26:00.0 0000:46:00.0 0000:65:00.0 0000:85:00.0 0000:a6:00.0 0000:c6:00.0 0000:e5:00.0 +GPU0 0000:05:00.0 32 Gb/s 512 Gb/s XGMI + Read N/A 1.123 PB 1.123 PB 1.123 PB 1.123 PB 1.123 PB 1.123 PB 1.123 PB + Write N/A 229.1 MB 229.1 MB 229.1 MB 229.1 MB 229.1 MB 229.1 MB 229.1 MB +GPU1 0000:26:00.0 32 Gb/s 512 Gb/s XGMI + Read 1.123 PB N/A 1.123 PB 1.123 PB 1.123 PB 1.123 PB 1.123 PB 1.123 PB + Write 229.1 MB N/A 229.1 MB 229.1 MB 229.1 MB 229.1 MB 229.1 MB 229.1 MB +GPU2 0000:46:00.0 32 Gb/s 512 Gb/s XGMI + Read 1.123 PB 1.123 PB N/A 1.123 PB 1.123 PB 1.123 PB 1.123 PB 1.123 PB + Write 229.1 MB 229.1 MB N/A 229.1 MB 229.1 MB 229.1 MB 229.1 MB 229.1 MB +... +``` + +### Resolved issues + +### Upcoming changes + +### Known issues + +- **AMD SMI only reports 63 GPU devices when setting CPX on all 8 GPUs** + When setting CPX as a partition mode, there is a DRM node limitation of 64. + + This is a known limitation of the Linux kernel, not the driver. Other drivers, such as those using PCIe space (e.g., ast), may be occupying the necessary DRM nodes. + + The number of DRM nodes used can be checked via `ls /sys/class/drm` + + Options are as follows: + 1) ***Workaround - removing other devices using DRM nodes*** + + Recommended steps for removing unnecessary drivers: + a. Unload amdgpu - `sudo rmmod amdgpu` + b. Remove unnecessary driver(s) - ex. `sudo rmmod ast` + c. Reload amgpu - `sudo modprobe amdgpu` + d. Confirm `amd-smi list` reports all nodes (this can vary per MI ASIC) + + 2) ***Update your OS' kernel*** + Typically you can find examples online by searching "`Update kernel command line`" + + Ex. "Update kernel Ubuntu 22.04 command line" should provide some good examples. + https://phoenixnap.com/kb/how-to-update-kernel-ubuntu + + 3) ***Building and installing your own kernel*** + *This option is helpful for users on OS distributions that have not yet merged the necessary changes.* + https://phoenixnap.com/kb/build-linux-kernel + + All changes are in the mainline kernel if users need to build their own. + + References to kernel changes: + ```text + for libdrm : + Author: James Zhu + + Date: Mon Aug 7 10:14:18 2023 -0400 + + xf86drm: use drm device name to identify drm node type + + Currently drm node's minor range is used to identify node's type. + + Since kernel drm uses node type name and minor to generate drm + + device name, It will be more general to use drm device name to + + identify drm node type. + + Signed-off-by: James Zhu + + Reviewed-by: Simon Ser + + commit 1080273c2b31db6f031a7f889f3104f53ab4502c + + Author: James Zhu + + Date: Mon Aug 7 10:06:32 2023 -0400 + + xf86drm: update DRM_NODE_NAME_MAX supporting more nodes + + Current DRM_NODE_NAME_MAX only can support up to 999 nodes, + + Update to support up to 2^MINORBITS nodes. + + Signed-off-by: James Zhu + + Reviewed-by: Simon Ser + ``` + +## amd_smi_lib for ROCm 6.3.1 + +### Added + +### Changed + +- **Changed `amd-smi monitor`: No longer display `ENC_CLOCK`/`DEC_CLOCK` but `VCLOCK` and `DCLOCK`**. + Due to fix mentioned in `Resolved Issues`, this change was needed. + Reason: Navi products use vclk and dclk for both encode and decode. On MI products, only decode is supported. + Before: + ```shell + $ amd-smi monitor -n -d + GPU ENC_UTIL ENC_CLOCK DEC_UTIL DEC_CLOCK + 0 0.0 % 29 MHz N/A 22 MHz + 1 0.0 % 29 MHz N/A 22 MHz + 2 0.0 % 29 MHz N/A 22 MHz + 3 0.0 % 29 MHz N/A 22 MHz + 4 0.0 % 29 MHz N/A 22 MHz + 5 0.0 % 29 MHz N/A 22 MHz + 6 0.0 % 29 MHz N/A 22 MHz + 7 0.0 % 29 MHz N/A 22 MHz + ``` + After: + ```shell + $ amd-smi monitor -n -d + GPU ENC_UTIL DEC_UTIL VCLOCK DCLOCK + 0 N/A 0.0 % 29 MHz 22 MHz + 1 N/A 0.0 % 29 MHz 22 MHz + 2 N/A 0.0 % 29 MHz 22 MHz + 3 N/A 0.0 % 29 MHz 22 MHz + 4 N/A 0.0 % 29 MHz 22 MHz + 5 N/A 0.0 % 29 MHz 22 MHz + 6 N/A 0.0 % 29 MHz 22 MHz + 7 N/A 0.0 % 29 MHz 22 MHz + ``` + +### Removed + +### Optimized + +### Resolved issues + +- **Fixed `amd-smi monitor`'s encode/decode: `ENC_UTIL`, `DEC_UTIL`, and now associate `VCLOCK`/`DCLOCK` with both**. + Navi products use vclk and dclk for both encode and decode. On MI products, only decode is supported. + + Navi products cannot support displaying ENC_UTIL % at this time. + + Before: + ```shell + $ amd-smi monitor -n -d + GPU ENC_UTIL ENC_CLOCK DEC_UTIL DEC_CLOCK + 0 0.0 % 29 MHz N/A 22 MHz + 1 0.0 % 29 MHz N/A 22 MHz + 2 0.0 % 29 MHz N/A 22 MHz + 3 0.0 % 29 MHz N/A 22 MHz + 4 0.0 % 29 MHz N/A 22 MHz + 5 0.0 % 29 MHz N/A 22 MHz + 6 0.0 % 29 MHz N/A 22 MHz + 7 0.0 % 29 MHz N/A 22 MHz + ``` + After: + ```shell + $ amd-smi monitor -n -d + GPU ENC_UTIL DEC_UTIL VCLOCK DCLOCK + 0 N/A 0.0 % 29 MHz 22 MHz + 1 N/A 0.0 % 29 MHz 22 MHz + 2 N/A 0.0 % 29 MHz 22 MHz + 3 N/A 0.0 % 29 MHz 22 MHz + 4 N/A 0.0 % 29 MHz 22 MHz + 5 N/A 0.0 % 29 MHz 22 MHz + 6 N/A 0.0 % 29 MHz 22 MHz + 7 N/A 0.0 % 29 MHz 22 MHz + ``` + +### Upcoming changes + +### Known issues ## amd_smi_lib for ROCm 6.3.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 85821c49ad..1a3b53dd81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ find_program(GIT NAMES git) ## Setup the package version based on git tags. set(PKG_VERSION_GIT_TAG_PREFIX "amdsmi_pkg_ver") -get_package_version_number("24.7.1" ${PKG_VERSION_GIT_TAG_PREFIX} GIT) +get_package_version_number("24.7.0" ${PKG_VERSION_GIT_TAG_PREFIX} GIT) message("Package version: ${PKG_VERSION_STR}") set(${AMD_SMI_LIBS_TARGET}_VERSION_MAJOR "${CPACK_PACKAGE_VERSION_MAJOR}") set(${AMD_SMI_LIBS_TARGET}_VERSION_MINOR "${CPACK_PACKAGE_VERSION_MINOR}") @@ -107,13 +107,6 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=2 -fno-common -Wstrict-overflow # Intentionally leave out -Wsign-promo. It causes spurious warnings. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Woverloaded-virtual -Wreorder") -# Add CMAKE debug flags -if ("${CMAKE_BUILD_TYPE}" STREQUAL Release) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2") -else () - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb -O0 -DDEBUG") -endif () - set(COMMON_SRC_DIR "${PROJECT_SOURCE_DIR}/src") set(ROCM_SRC_DIR "${PROJECT_SOURCE_DIR}/rocm_smi/src") set(AMDSMI_SRC_DIR "${PROJECT_SOURCE_DIR}/src/amd_smi") @@ -128,9 +121,8 @@ if(ENABLE_ESMI_LIB) execute_process(COMMAND git clone --depth=1 -b esmi_pkg_ver-3.0.3 https://github.com/amd/esmi_ib_library.git ${PROJECT_SOURCE_DIR}/esmi_ib_library) endif() if(NOT EXISTS ${PROJECT_SOURCE_DIR}/esmi_ib_library/include/asm/amd_hsmp.h) - file(DOWNLOAD - https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/plain/arch/x86/include/uapi/asm/amd_hsmp.h?h=review-ilpo - ${PROJECT_SOURCE_DIR}/esmi_ib_library/include/asm/amd_hsmp.h) + file(COPY "${PROJECT_SOURCE_DIR}/include/amd_smi/impl/amd_hsmp.h" + DESTINATION "${PROJECT_SOURCE_DIR}/esmi_ib_library/include/asm") endif() add_definitions("-DENABLE_ESMI_LIB=1") set(ESMI_INC_DIR "${PROJECT_SOURCE_DIR}/esmi_ib_library/include") @@ -261,10 +253,10 @@ install( add_subdirectory(goamdsmi_shim) #Debian package specific variables -set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "python3-argcomplete, libdrm-dev, python3-yaml") +set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "python3-argcomplete, libdrm-dev") set(CPACK_DEBIAN_ASAN_PACKAGE_RECOMMENDS ${CPACK_DEBIAN_PACKAGE_RECOMMENDS}) set(CPACK_DEBIAN_DEV_PACKAGE_RECOMMENDS ${CPACK_DEBIAN_PACKAGE_RECOMMENDS}) -set(CPACK_DEBIAN_PACKAGE_DEPENDS "sudo, python3 (>= 3.6.8), python3-pip") +set(CPACK_DEBIAN_PACKAGE_DEPENDS "sudo, python3 (>= 3.6.8), python3-pip, python3-setuptools, python3-wheel") set(CPACK_DEBIAN_ASAN_PACKAGE_DEPENDS ${CPACK_DEBIAN_PACKAGE_DEPENDS}) set(CPACK_DEBIAN_DEV_PACKAGE_DEPENDS ${CPACK_DEBIAN_PACKAGE_DEPENDS}) @@ -285,7 +277,7 @@ set(CPACK_RPM_PACKAGE_SUGGESTS "python3-argcomplete") set(CPACK_RPM_DEV_PACKAGE_SUGGESTS ${CPACK_RPM_PACKAGE_SUGGESTS}) set(CPACK_RPM_ASAN_PACKAGE_SUGGESTS ${CPACK_RPM_PACKAGE_SUGGESTS}) # python version gated by rhel8 :( -set(CPACK_RPM_PACKAGE_REQUIRES "sudo, python3 >= 3.6.8, python3-pip, python3-PyYAML") +set(CPACK_RPM_PACKAGE_REQUIRES "sudo, python3 >= 3.6.8, python3-pip, python3-setuptools, python3-wheel") set(CPACK_RPM_DEV_PACKAGE_REQUIRES ${CPACK_RPM_PACKAGE_REQUIRES}) set(CPACK_RPM_ASAN_PACKAGE_REQUIRES ${CPACK_RPM_PACKAGE_REQUIRES}) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..a79d7c0520 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,31 @@ + # Use ubuntu 20.04 base image + FROM compute-artifactory.amd.com:5000/rocm-base-images/ubuntu-20.04-bld:2024112501 + + # Set environment variables + ENV BUILD_FOLDER=/src/build + ENV DEB_BUILD="amd-smi-lib*99999-local_amd64.deb" + ENV DEB_BUILD_TEST='amd-smi-lib-tests*99999-local_amd64.deb' + + # Set up the working directory + WORKDIR /src + + # Copy the source code into the container + COPY . /src + + # Run the build and install commands + RUN rm -rf ${BUILD_FOLDER} && \ + mkdir -p ${BUILD_FOLDER} && \ + cd ${BUILD_FOLDER} && \ + cmake .. -DBUILD_TESTS=ON -DENABLE_ESMI_LIB=ON && \ + make -j $(nproc) VERBOSE=1 && \ + make package && \ + sudo apt install -y ${BUILD_FOLDER}/${DEB_BUILD} && \ + sudo ln -s /opt/rocm/bin/amd-smi /usr/local/bin + + # Verify installation + RUN python3 -m pip list | grep amd && \ + python3 -m pip list | grep pip && \ + python3 -m pip list | grep setuptools + + # Set the entrypoint + ENTRYPOINT ["/bin/bash"] diff --git a/amdsmi_cli/amdsmi_cli.py b/amdsmi_cli/amdsmi_cli.py index 15fe9051c2..ddec9921bb 100755 --- a/amdsmi_cli/amdsmi_cli.py +++ b/amdsmi_cli/amdsmi_cli.py @@ -100,6 +100,8 @@ if __name__ == "__main__": except NameError: logging.debug("argcomplete module not found. Autocomplete will not work.") + sys.argv = [arg.lower() if arg.startswith('--') or not arg.startswith('-') + else arg for arg in sys.argv] args = amd_smi_parser.parse_args(args=None if sys.argv[1:] else ['--help']) # Handle command modifiers before subcommand execution diff --git a/amdsmi_cli/amdsmi_commands.py b/amdsmi_cli/amdsmi_commands.py index 79971db3a4..957b2c8031 100644 --- a/amdsmi_cli/amdsmi_commands.py +++ b/amdsmi_cli/amdsmi_commands.py @@ -31,7 +31,7 @@ import os from _version import __version__ from amdsmi_helpers import AMDSMIHelpers from amdsmi_logger import AMDSMILogger -from amdsmi_cli_exceptions import AmdSmiRequiredCommandException +from amdsmi_cli_exceptions import AmdSmiRequiredCommandException, AmdSmiInvalidParameterException from rocm_version import get_rocm_version from amdsmi import amdsmi_interface from amdsmi import amdsmi_exception @@ -271,7 +271,7 @@ class AMDSMICommands(): def static_gpu(self, args, multiple_devices=False, gpu=None, asic=None, bus=None, vbios=None, limit=None, driver=None, ras=None, board=None, numa=None, vram=None, cache=None, partition=None, dfc_ucode=None, fb_info=None, num_vf=None, - soc_pstate=None, xgmi_plpd=None, process_isolation=None): + soc_pstate=None, xgmi_plpd=None, process_isolation=None, clock=None): """Get Static information for target gpu Args: @@ -321,12 +321,19 @@ class AMDSMICommands(): args.cache = cache if process_isolation: args.process_isolation = process_isolation + if clock: + args.clock = clock + # args.clock defaults to False so if it was overwritten to empty list, that indicates that it was given as an arguments but with an empty list + if args.clock == []: + args.clock = True # Store args that are applicable to the current platform current_platform_args = ["asic", "bus", "vbios", "driver", "ras", - "vram", "cache", "board", "process_isolation"] + "vram", "cache", "board", "process_isolation", + "clock"] current_platform_values = [args.asic, args.bus, args.vbios, args.driver, args.ras, - args.vram, args.cache, args.board, args.process_isolation] + args.vram, args.cache, args.board, args.process_isolation, + args.clock] if self.helpers.is_linux() and self.helpers.is_baremetal(): if partition: @@ -829,6 +836,58 @@ class AMDSMICommands(): logging.debug("Failed to get cache info for gpu %s | %s", gpu_id, e.get_error_info()) static_dict['cache_info'] = cache_info_list + if 'clock' in current_platform_args: + if isinstance(args.clock, bool) and args.clock == True: + args.clock = ['sys', 'mem', 'df', 'soc', 'dcef', 'vclk0', 'vclk1', 'dclk0', 'dclk1'] + if isinstance(args.clock, list): + # remove potential duplicates from list + args.clock = list(set(args.clock)) + # check that clock is valid option + if "all" in args.clock or len(args.clock) == 0: + args.clock = ['sys', 'mem', 'df', 'soc', 'dcef', 'vclk0', 'vclk1', 'dclk0', 'dclk1'] + clk_dict = {} + + for clk in args.clock: + clk_type = clk.lower() + if clk_type == "sys": + clk_type_conversion = amdsmi_interface.AmdSmiClkType.SYS + elif clk_type == "mem": + clk_type_conversion = amdsmi_interface.AmdSmiClkType.MEM + elif clk_type == "df": + clk_type_conversion = amdsmi_interface.AmdSmiClkType.DF + elif clk_type == "soc": + clk_type_conversion = amdsmi_interface.AmdSmiClkType.SOC + elif clk_type == "dcef": + clk_type_conversion = amdsmi_interface.AmdSmiClkType.DCEF + # vclk and dclk currently do not support levels so average clk is given for frequency levels + elif clk_type == "vclk0": + clk_type_conversion = amdsmi_interface.AmdSmiClkType.VCLK0 + elif clk_type == "vclk1": + clk_type_conversion = amdsmi_interface.AmdSmiClkType.VCLK1 + elif clk_type == "dclk0": + clk_type_conversion = amdsmi_interface.AmdSmiClkType.DCLK0 + elif clk_type == "dclk1": + clk_type_conversion = amdsmi_interface.AmdSmiClkType.DCLK1 + else: + clk_type_conversion = "N/A" + output_format = self.helpers.get_output_format() + raise AmdSmiInvalidParameterException(clk_type, output_format) # clk type given is bad + + try: + frequencies = amdsmi_interface.amdsmi_get_clk_freq(args.gpu, clk_type_conversion) + freq_dict = {} + freq_dict.update({'current level':frequencies['current']}) + freq_dict.update({'frequency_levels':{}}) + for level in range(len(frequencies['frequency'])): + freq = str(self.helpers.convert_SI_unit(frequencies['frequency'][level], AMDSMIHelpers.SI_Unit.MICRO)) + " MHz" + freq_dict['frequency_levels'].update({level:freq}) + except amdsmi_exception.AmdSmiLibraryException as e: + freq_dict = "N/A" + clk_dict.update({clk:freq_dict}) + + static_dict['clock'] = clk_dict + else: + raise amdsmi_exception.AmdSmiParameterException(args.clock, list[str]) # Convert and store output by pid for csv format multiple_devices_csv_override = False @@ -864,7 +923,8 @@ class AMDSMICommands(): bus=None, vbios=None, limit=None, driver=None, ras=None, board=None, numa=None, vram=None, cache=None, partition=None, dfc_ucode=None, fb_info=None, num_vf=None, cpu=None, - interface_ver=None, soc_pstate=None, xgmi_plpd = None, process_isolation=None): + interface_ver=None, soc_pstate=None, xgmi_plpd = None, process_isolation=None, + clock=None): """Get Static information for target gpu and cpu Args: @@ -916,7 +976,7 @@ class AMDSMICommands(): gpu_attributes = ["asic", "bus", "vbios", "limit", "driver", "ras", "board", "numa", "vram", "cache", "partition", "dfc_ucode", "fb_info", "num_vf", "soc_pstate", "xgmi_plpd", - "process_isolation"] + "process_isolation", "clock"] for attr in gpu_attributes: if hasattr(args, attr): if getattr(args, attr): @@ -947,7 +1007,7 @@ class AMDSMICommands(): bus, vbios, limit, driver, ras, board, numa, vram, cache, partition, dfc_ucode, fb_info, num_vf, soc_pstate, - process_isolation) + process_isolation, clock) elif self.helpers.is_amd_hsmp_initialized(): # Only CPU is initialized if args.cpu == None: args.cpu = self.cpu_handles @@ -962,7 +1022,7 @@ class AMDSMICommands(): bus, vbios, limit, driver, ras, board, numa, vram, cache, partition, dfc_ucode, fb_info, num_vf, soc_pstate, xgmi_plpd, - process_isolation) + process_isolation, clock) def firmware(self, args, multiple_devices=False, gpu=None, fw_list=True): @@ -1471,7 +1531,6 @@ class AMDSMICommands(): engine_usage['gfx_busy_inst'] = "N/A" engine_usage['jpeg_busy'] = "N/A" engine_usage['vcn_busy'] = "N/A" - engine_usage['gfx_busy_acc'] = "N/A" if num_partition != "N/A": # these are one after another, in order to display each in sub-sections @@ -1490,11 +1549,6 @@ class AMDSMICommands(): new_xcp_dict[f"xcp_{current_xcp}"] = gpu_metric['xcp_stats.vcn_busy'][current_xcp] engine_usage['vcn_busy'] = new_xcp_dict - new_xcp_dict = {} - for current_xcp in range(num_partition): - new_xcp_dict[f"xcp_{current_xcp}"] = gpu_metric['xcp_stats.gfx_busy_acc'][current_xcp] - engine_usage['gfx_busy_acc'] = new_xcp_dict - logging.debug(f"After updates to engine_usage dictionary = {engine_usage}") for key, value in engine_usage.items(): @@ -1628,6 +1682,18 @@ class AMDSMICommands(): "clk_locked" : "N/A", "deep_sleep" : "N/A"} + clocks["fclk_0"] = {"clk" : "N/A", + "min_clk" : "N/A", + "max_clk" : "N/A", + "clk_locked" : "N/A", + "deep_sleep" : "N/A"} + + clocks["socclk_0"] = {"clk" : "N/A", + "min_clk" : "N/A", + "max_clk" : "N/A", + "clk_locked" : "N/A", + "deep_sleep" : "N/A"} + clock_unit = "MHz" # TODO make the deepsleep threshold correspond to the * in sysfs for current deep sleep status deep_sleep_threshold = 140 @@ -1705,6 +1771,31 @@ class AMDSMICommands(): clocks[dclk_index]["deep_sleep"] = "ENABLED" else: clocks[dclk_index]["deep_sleep"] = "DISABLED" + + # Populate FCLK clock value; fclk not present in gpu_metrics so use amdsmi_get_clk_freq + frequency_dict = amdsmi_interface.amdsmi_get_clk_freq(args.gpu, amdsmi_interface.AmdSmiClkType.DF) + current_fclk_clock = frequency_dict['frequency'][frequency_dict['current']] + current_fclk_clock = self.helpers.convert_SI_unit(current_fclk_clock, self.helpers.SI_Unit.MICRO) + clocks["fclk_0"]["clk"] = self.helpers.unit_format(self.logger, + current_fclk_clock, + clock_unit) + + if int(current_fclk_clock) <= deep_sleep_threshold: + clocks["fclk_0"]["deep_sleep"] = "ENABLED" + else: + clocks["fclk_0"]["deep_sleep"] = "DISABLED" + + # Populate SOCCLK clock value + current_socclk_clock = gpu_metric["current_socclk"] + clocks["socclk_0"]["clk"] = self.helpers.unit_format(self.logger, + current_socclk_clock, + clock_unit) + + if int(current_socclk_clock) <= deep_sleep_threshold: + clocks["socclk_0"]["deep_sleep"] = "ENABLED" + else: + clocks["socclk_0"]["deep_sleep"] = "DISABLED" + except Exception as e: logging.debug("Failed to get gpu_metrics_info for gpu %s | %s", gpu_id, e) @@ -1777,6 +1868,36 @@ class AMDSMICommands(): except amdsmi_exception.AmdSmiLibraryException as e: logging.debug("Failed to get vclk and/or dclk clock info for gpu %s | %s", gpu_id, e.get_error_info()) + # FCLK min and max clocks + try: + fclk_clk_info_dict = amdsmi_interface.amdsmi_get_clock_info(args.gpu, + amdsmi_interface.AmdSmiClkType.DF) + # if the current clock is N/A then we shouldn't populate the max and min values + if clocks["fclk_0"]["clk"] != "N/A": + clocks["fclk_0"]["min_clk"] = self.helpers.unit_format(self.logger, + fclk_clk_info_dict["min_clk"], + clock_unit) + clocks["fclk_0"]["max_clk"] = self.helpers.unit_format(self.logger, + fclk_clk_info_dict["max_clk"], + clock_unit) + except amdsmi_exception.AmdSmiLibraryException as e: + logging.debug("Failed to get fclk info for gpu %s | %s", gpu_id, e.get_error_info()) + + # SOCCLK min and max clocks + try: + socclk_clk_info_dict = amdsmi_interface.amdsmi_get_clock_info(args.gpu, + amdsmi_interface.AmdSmiClkType.SOC) + # if the current clock is N/A then we shouldn't populate the max and min values + if clocks["socclk_0"]["clk"] != "N/A": + clocks["socclk_0"]["min_clk"] = self.helpers.unit_format(self.logger, + socclk_clk_info_dict["min_clk"], + clock_unit) + clocks["socclk_0"]["max_clk"] = self.helpers.unit_format(self.logger, + socclk_clk_info_dict["max_clk"], + clock_unit) + except amdsmi_exception.AmdSmiLibraryException as e: + logging.debug("Failed to get socclk info for gpu %s | %s", gpu_id, e.get_error_info()) + values_dict['clock'] = clocks if "temperature" in current_platform_args: if args.temperature: @@ -3843,7 +3964,7 @@ class AMDSMICommands(): def set_gpu(self, args, multiple_devices=False, gpu=None, fan=None, perf_level=None, profile=None, perf_determinism=None, compute_partition=None, memory_partition=None, power_cap=None, soc_pstate=None, xgmi_plpd = None, - process_isolation=None, clk_limit=None): + process_isolation=None, clk_limit=None, clk_level=None): """Issue reset commands to target gpu(s) Args: @@ -3892,6 +4013,8 @@ class AMDSMICommands(): args.process_isolation = process_isolation if clk_limit: args.clk_limit = clk_limit + if clk_level: + args.clk_level = clk_level # Handle No GPU passed if args.gpu == None: @@ -3915,6 +4038,7 @@ class AMDSMICommands(): args.power_cap is not None, args.soc_pstate is not None, args.xgmi_plpd is not None, + args.clk_level is not None, args.clk_limit is not None, args.process_isolation is not None]): command = " ".join(sys.argv[1:]) @@ -4166,6 +4290,62 @@ class AMDSMICommands(): raise PermissionError('Command requires elevation') from e raise ValueError(f"Unable to set XGMI policy to {args.xgmi_plpd} on {gpu_string}") from e self.logger.store_output(args.gpu, 'xgmiplpd', f"Successfully set per-link power down policy to id {args.xgmi_plpd}") + if isinstance(args.clk_level, tuple): + clk_type = args.clk_level.clk_type + perf_levels = args.clk_level.perf_levels + + # check if perf levels are all valid levels + try: + if clk_type == "sclk": + clk_type_conversion = amdsmi_interface.AmdSmiClkType.SYS + elif clk_type == "mclk": + clk_type_conversion = amdsmi_interface.AmdSmiClkType.MEM + elif clk_type == "pcie": + clk_type_conversion = amdsmi_interface.AmdSmiClkType.PCIE + elif clk_type == "fclk": + clk_type_conversion = amdsmi_interface.AmdSmiClkType.DF + elif clk_type == "socclk": + clk_type_conversion = amdsmi_interface.AmdSmiClkType.SOC + else: + clk_type_conversion = "N/A" + frequencies = amdsmi_interface.amdsmi_get_clk_freq(args.gpu, clk_type_conversion) + num_supported = frequencies['num_supported'] + except amdsmi_exception.AmdSmiLibraryException as e: + pass + + # convert perf_levels given to freq bit mask + freq_mask = 0 + valid_level = True + invalid_levels = [] + for level in perf_levels: + if level < num_supported: + freq_mask += 2**level + else: + # cancel this instance since the level should not be possible + invalid_levels.append(level) + valid_level = False + + if valid_level: + perf_levels_str = str(perf_levels).strip('[]') + if clk_type.lower() == "pcie": + try: + amdsmi_interface.amdsmi_set_gpu_pci_bandwidth(args.gpu, freq_mask) + except amdsmi_exception.AmdSmiLibraryException as e: + if e.get_error_code() == amdsmi_interface.amdsmi_wrapper.AMDSMI_STATUS_NO_PERM: + raise PermissionError('Command requires elevation') from e + raise ValueError(f"Unable to set pcie bandwidth to perf level(s) {perf_levels_str} on {gpu_string}") from e + else: + try: + amdsmi_interface.amdsmi_set_clk_freq(args.gpu, clk_type, freq_mask) + except amdsmi_exception.AmdSmiLibraryException as e: + if e.get_error_code() == amdsmi_interface.amdsmi_wrapper.AMDSMI_STATUS_NO_PERM: + raise PermissionError('Command requires elevation') from e + raise ValueError(f"Unable to set {clk_type} to perf level(s) {perf_levels_str} on {gpu_string}") from e + self.logger.store_output(args.gpu, 'clk_level', f"Successfully changed {clk_type} perf level(s) to {perf_levels_str}") + else: + invalid_levels_str = str(invalid_levels).strip('[]') + self.logger.store_output(args.gpu, 'clk_level', f"level(s) {invalid_levels_str} is/are greater than performance levels supported for device") + if isinstance(args.clk_limit, tuple): clk_type = args.clk_limit.clk_type lim_type = args.clk_limit.lim_type @@ -4240,7 +4420,7 @@ class AMDSMICommands(): cpu_pwr_eff_mode=None, cpu_gmi3_link_width=None, cpu_pcie_link_rate=None, cpu_df_pstate_range=None, cpu_enable_apb=None, cpu_disable_apb=None, soc_boost_limit=None, core=None, core_boost_limit=None, soc_pstate=None, xgmi_plpd=None, - process_isolation=None, clk_limit=None): + process_isolation=None, clk_limit=None, clk_level=None): """Issue reset commands to target gpu(s) Args: @@ -4292,7 +4472,7 @@ class AMDSMICommands(): gpu_args_enabled = False gpu_attributes = ["fan", "perf_level", "profile", "perf_determinism", "compute_partition", "memory_partition", "power_cap", "soc_pstate", "xgmi_plpd", - "process_isolation", "clk_limit"] + "process_isolation", "clk_limit", "clk_level"] for attr in gpu_attributes: if hasattr(args, attr): if getattr(args, attr) is not None: @@ -4318,6 +4498,18 @@ class AMDSMICommands(): core_args_enabled = True break + # Error if no subcommand args are passed + if self.helpers.is_baremetal(): + if not any([args.gpu, args.fan, args.perf_level, args.profile, args.perf_determinism, \ + args.compute_partition, args.memory_partition, args.power_cap,\ + args.soc_pstate, args.xgmi_plpd, args.clk_limit, args.process_isolation]): + command = " ".join(sys.argv[1:]) + raise AmdSmiRequiredCommandException(command, self.logger.format) + else: + if not any([args.clean_local_data]): + command = " ".join(sys.argv[1:]) + raise AmdSmiRequiredCommandException(command, self.logger.format) + # Only allow one device's arguments to be set at a time if not any([gpu_args_enabled, cpu_args_enabled, core_args_enabled]): raise ValueError('No GPU, CPU, or CORE arguments provided, specific arguments are needed') @@ -4348,7 +4540,7 @@ class AMDSMICommands(): self.set_gpu(args, multiple_devices, gpu, fan, perf_level, profile, perf_determinism, compute_partition, memory_partition, power_cap, soc_pstate, xgmi_plpd, - process_isolation, clk_limit) + process_isolation, clk_limit, clk_level) elif self.helpers.is_amd_hsmp_initialized(): # Only CPU is initialized if args.cpu == None and args.core == None: raise ValueError('No CPU or CORE provided, specific target(s) are needed') @@ -4368,7 +4560,7 @@ class AMDSMICommands(): self.set_gpu(args, multiple_devices, gpu, fan, perf_level, profile, perf_determinism, compute_partition, memory_partition, power_cap, soc_pstate, xgmi_plpd, - process_isolation, clk_limit) + process_isolation, clk_limit, clk_level) def reset(self, args, multiple_devices=False, gpu=None, gpureset=None, @@ -4717,6 +4909,23 @@ class AMDSMICommands(): self.logger.store_output(args.gpu, 'timestamp', int(time.time())) self.logger.table_header = 'TIMESTAMP'.rjust(10) + ' ' + self.logger.table_header + if args.loglevel == "DEBUG": + try: + # Get GPU Metrics table version + gpu_metric_version_info = amdsmi_interface.amdsmi_get_gpu_metrics_header_info(args.gpu) + gpu_metric_version_str = json.dumps(gpu_metric_version_info, indent=4) + logging.debug("GPU Metrics table Version for GPU %s | %s", gpu_id, gpu_metric_version_str) + except amdsmi_exception.AmdSmiLibraryException as e: + logging.debug("Unable to load GPU Metrics table version for %s | %s", gpu_id, e.err_info) + + try: + # Get GPU Metrics table + gpu_metric_debug_info = amdsmi_interface.amdsmi_get_gpu_metrics_info(args.gpu) + gpu_metric_str = json.dumps(gpu_metric_debug_info, indent=4) + logging.debug("GPU Metrics table for GPU %s | %s", gpu_id, str(gpu_metric_str)) + except amdsmi_exception.AmdSmiLibraryException as e: + logging.debug("Unable to load GPU Metrics table for %s | %s", gpu_id, e.err_info) + # Store the pcie_bw values due to possible increase in bandwidth due to repeated gpu_metrics calls if args.pcie: try: @@ -4845,9 +5054,10 @@ class AMDSMICommands(): self.logger.table_header += 'MEM_CLOCK'.rjust(11) if args.encoder: + # TODO: The encoding utilization is in progress for Navi. Note: MI3x ASICs only support decoding. try: # Get List of vcn activity values - encoder_util = amdsmi_interface.amdsmi_get_gpu_metrics_info(args.gpu)['vcn_activity'] + encoder_util = "N/A" # Not yet implemented encoding_activity_avg = [] for value in encoder_util: if isinstance(value, int): @@ -4874,49 +5084,72 @@ class AMDSMICommands(): self.logger.table_header += 'ENC_UTIL'.rjust(10) - try: - encoder_clock = amdsmi_interface.amdsmi_get_gpu_metrics_info(args.gpu)['current_vclk0'] - monitor_values['encoder_clock'] = encoder_clock - freq_unit = 'MHz' - if encoder_clock != "N/A": - if self.logger.is_human_readable_format(): - monitor_values['encoder_clock'] = f"{monitor_values['encoder_clock']} {freq_unit}" - if self.logger.is_json_format(): - monitor_values['encoder_clock'] = {"value" : monitor_values['encoder_clock'], - "unit" : freq_unit} - except amdsmi_exception.AmdSmiLibraryException as e: - monitor_values['encoder_clock'] = "N/A" - logging.debug("Failed to get encoder clock on gpu %s | %s", gpu_id, e.get_error_info()) - - self.logger.table_header += 'ENC_CLOCK'.rjust(11) if args.decoder: try: - decoder_util = "N/A" # Not yet implemented - monitor_values['decoder'] = decoder_util - # if self.logger.is_human_readable_format(): - # monitor_values['decoder'] = f"{monitor_values['decoder']} %" + # Get List of vcn activity values + # Note: MI3x ASICs only support decoding, so the vcn_activity is used for decoding activity. + decoder_util = amdsmi_interface.amdsmi_get_gpu_metrics_info(args.gpu)['vcn_activity'] + decoding_activity_avg = [] + for value in decoder_util: + if isinstance(value, int): + decoding_activity_avg.append(value) + + # Averaging the possible decoding activity values + if decoding_activity_avg: + decoding_activity_avg = sum(decoding_activity_avg) / len(decoding_activity_avg) + else: + decoding_activity_avg = "N/A" + + monitor_values['decoder'] = decoding_activity_avg + + activity_unit = '%' + if monitor_values['decoder'] != "N/A": + if self.logger.is_human_readable_format(): + monitor_values['decoder'] = f"{monitor_values['decoder']} {activity_unit}" + if self.logger.is_json_format(): + monitor_values['decoder'] = {"value" : monitor_values['decoder'], + "unit" : activity_unit} except amdsmi_exception.AmdSmiLibraryException as e: monitor_values['decoder'] = "N/A" logging.debug("Failed to get decoder utilization on gpu %s | %s", gpu_id, e.get_error_info()) self.logger.table_header += 'DEC_UTIL'.rjust(10) + if args.encoder or args.decoder: try: - decoder_clock = amdsmi_interface.amdsmi_get_gpu_metrics_info(args.gpu)['current_dclk0'] - monitor_values['decoder_clock'] = decoder_clock + vclock = amdsmi_interface.amdsmi_get_gpu_metrics_info(args.gpu)['current_vclk0'] + monitor_values['vclock'] = vclock freq_unit = 'MHz' - if decoder_clock != "N/A": + if vclock != "N/A": if self.logger.is_human_readable_format(): - monitor_values['decoder_clock'] = f"{monitor_values['decoder_clock']} {freq_unit}" + monitor_values['vclock'] = f"{monitor_values['vclock']} {freq_unit}" if self.logger.is_json_format(): - monitor_values['decoder_clock'] = {"value" : monitor_values['decoder_clock'], + monitor_values['vclock'] = {"value" : monitor_values['vclock'], "unit" : freq_unit} except amdsmi_exception.AmdSmiLibraryException as e: - monitor_values['decoder_clock'] = "N/A" - logging.debug("Failed to get decoder clock on gpu %s | %s", gpu_id, e.get_error_info()) + monitor_values['vclock'] = "N/A" + logging.debug("Failed to get dclock on gpu %s | %s", gpu_id, e.get_error_info()) + + self.logger.table_header += 'VCLOCK'.rjust(8) + + try: + dclock = amdsmi_interface.amdsmi_get_gpu_metrics_info(args.gpu)['current_dclk0'] + monitor_values['dclock'] = dclock + + freq_unit = 'MHz' + if dclock != "N/A": + if self.logger.is_human_readable_format(): + monitor_values['dclock'] = f"{monitor_values['dclock']} {freq_unit}" + if self.logger.is_json_format(): + monitor_values['dclock'] = {"value" : monitor_values['dclock'], + "unit" : freq_unit} + except amdsmi_exception.AmdSmiLibraryException as e: + monitor_values['dclock'] = "N/A" + logging.debug("Failed to get vclock on gpu %s | %s", gpu_id, e.get_error_info()) + + self.logger.table_header += 'DCLOCK'.rjust(8) - self.logger.table_header += 'DEC_CLOCK'.rjust(11) if args.ecc: try: ecc = amdsmi_interface.amdsmi_get_gpu_total_ecc_count(args.gpu) @@ -5245,8 +5478,8 @@ class AMDSMICommands(): data_unit = 'KB' if self.logger.is_human_readable_format(): - dest_link_dict['read'] = f"{read} {data_unit}" - dest_link_dict['write'] = f"{write} {data_unit}" + dest_link_dict['read'] = self.helpers.convert_bytes_to_readable(read * 1024, True) + dest_link_dict['write'] = self.helpers.convert_bytes_to_readable(write * 1024, True) elif self.logger.is_json_format(): dest_link_dict['read'] = {"value" : read, "unit" : data_unit} @@ -5297,8 +5530,8 @@ class AMDSMICommands(): tabular_output.append(tabular_output_dict) # Create Read and Write rows and add to tabular_output - read_output_dict = {"RW" : "Read"} - write_output_dict = {"RW" : "Write"} + read_output_dict = {"RW" : " Read"} + write_output_dict = {"RW" : " Write"} for key, value in xgmi_dict.items(): if key == "link_metrics": for link_key, link_value in value.items(): @@ -5550,7 +5783,14 @@ class AMDSMICommands(): events = listener.read(2000) for event in events: values_dict["event"] = event["event"] - values_dict["message"] = event["message"] + # parse message as it's own dictionary + message_list = event["message"].split(" ") + message_dict = {} + for item in message_list: + if not item == "": + item_list = item.split(": ") + message_dict.update({item_list[0]: item_list[1]}) + values_dict["message"] = message_dict commands.logger.store_output(device, 'values', values_dict) commands.logger.print_output() except amdsmi_exception.AmdSmiLibraryException as e: diff --git a/amdsmi_cli/amdsmi_helpers.py b/amdsmi_cli/amdsmi_helpers.py index 2fce5f4940..7018d8f72f 100644 --- a/amdsmi_cli/amdsmi_helpers.py +++ b/amdsmi_cli/amdsmi_helpers.py @@ -779,10 +779,20 @@ class AMDSMIHelpers(): return False, profile_presets.values() - def convert_bytes_to_readable(self, bytes_input): + def convert_bytes_to_readable(self, bytes_input, format_length=None): for unit in ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]: if abs(bytes_input) < 1024: - return f"{bytes_input:3.1f} {unit}" + if format_length is not None: + if bytes_input < 10: + return f"{bytes_input:4.3f} {unit}" + elif bytes_input < 100: + return f"{bytes_input:4.2f} {unit}" + elif bytes_input < 1000: + return f"{bytes_input:4.1f} {unit}" + else: + return f"{bytes_input:4.0f} {unit}" + else: + return f"{bytes_input:3.1f} {unit}" bytes_input /= 1024 return f"{bytes_input:.1f} YB" diff --git a/amdsmi_cli/amdsmi_logger.py b/amdsmi_cli/amdsmi_logger.py index a409d4f578..f967910f7e 100644 --- a/amdsmi_cli/amdsmi_logger.py +++ b/amdsmi_cli/amdsmi_logger.py @@ -25,20 +25,10 @@ import re import time from typing import Dict from enum import Enum -import yaml import inspect - from amdsmi_helpers import AMDSMIHelpers import amdsmi_cli_exceptions -### Custom YAML Functions -# Dumper class to preserve order of yaml.dump -class CustomDumper(yaml.Dumper): - def represent_dict_preserve_order(self, data): - return self.represent_dict(data.items()) -def has_sort_keys_option(): # to check if sort_keys is available - return 'sort_keys' in inspect.signature(yaml.dump).parameters - class AMDSMILogger(): def __init__(self, format='human_readable', destination='stdout') -> None: self.output = {} @@ -127,8 +117,10 @@ class AMDSMILogger(): table_values += string_value.rjust(10) + ' ' elif key == 'power_usage': table_values += string_value.rjust(7) - elif key in ('gfx_clock', 'mem_clock', 'encoder_clock', 'decoder_clock', 'vram_used'): + elif key in ('gfx_clock', 'mem_clock', 'vram_used'): table_values += string_value.rjust(11) + elif key in ('vclock', 'dclock'): + table_values += string_value.rjust(8) elif key == 'vram_total' or 'ecc' in key or key == 'pcie_bw': table_values += string_value.rjust(12) elif key in ['pcie_replay']: @@ -174,7 +166,7 @@ class AMDSMILogger(): elif key == "resources_shared": table_values += string_value.ljust(18) elif key == "RW": - table_values += string_value.ljust(52) + table_values += string_value.ljust(53) elif key == "process_list": #Add an additional padding between the first instance of GPU and NAME table_values += ' ' @@ -233,15 +225,8 @@ class AMDSMILogger(): capitalized_json["AMDSMI_SPACING_REMOVAL"] = tabbed_dictionary - json_string = json.dumps(capitalized_json, indent=4) - - if has_sort_keys_option(): - yaml_data = yaml.safe_load(json_string) - yaml_output = yaml.dump(yaml_data, sort_keys=False, allow_unicode=True) - else: - CustomDumper.add_representer(dict, CustomDumper.represent_dict_preserve_order) - yaml_data = yaml.safe_load(json_string) - yaml_output = yaml.dump(yaml_data, Dumper=CustomDumper, allow_unicode=True, default_flow_style=False) + # Convert the capitalized JSON to a YAML-like string + yaml_output = self.custom_dump(capitalized_json) # Remove a key line if it is a spacer yaml_output = yaml_output.replace("AMDSMI_SPACING_REMOVAL:\n", "") @@ -264,6 +249,22 @@ class AMDSMILogger(): return clean_yaml_output + def custom_dump(self, data, indent=0): + """Converts a Python dictionary to a YAML-like string.""" + yaml_string = "" + for key, value in data.items(): + if isinstance(value, dict): + yaml_string += " " * indent + f"{key}:\n" + self.custom_dump(value, indent + 1) + elif isinstance(value, list): + yaml_string += " " * indent + f"{key}:\n" + for item in value: + if isinstance(item, dict): + yaml_string += self.custom_dump(item, indent + 1) + else: # If the list is not a dictionary, print it as a string + yaml_string += " " * (indent + 1) + f"- {item}\n" + else: + yaml_string += " " * indent + f"{key}: {value}\n" + return yaml_string def flatten_dict(self, target_dict, topology_override=False): """This will flatten a dictionary out to a single level of key value stores diff --git a/amdsmi_cli/amdsmi_parser.py b/amdsmi_cli/amdsmi_parser.py index 27d0aeb601..a6fbbc0c15 100644 --- a/amdsmi_cli/amdsmi_parser.py +++ b/amdsmi_cli/amdsmi_parser.py @@ -203,6 +203,37 @@ class AMDSMIParser(argparse.ArgumentParser): return AMDSMILimitArgs + def _level_select(self): + """Custom action for setting clock frequencies to particular performance level""" + output_format = self.helpers.get_output_format() + + class AMDSMIFreqArgs(argparse.Action): + def __call__(self, parser: AMDSMIParser, namespace: argparse.Namespace, + values: list, option_string: Optional[str] = None) -> None: + # valid values + valid_clk_types = ('sclk', 'mclk', 'pcie', 'fclk', 'socclk') + clk_type = values[0] + perf_levels_str = values[1:] + + # Check if the sclk and mclk parameters are valid + if clk_type not in valid_clk_types: + raise amdsmi_cli_exceptions.AmdSmiInvalidParameterException(clk_type, output_format) + + perf_levels = [] + # Check if every item in perf level is valid + for level in perf_levels_str: + if not level.isdigit(): + raise amdsmi_cli_exceptions.AmdSmiInvalidParameterValueException(level, output_format) + level = int(level) + if level < 0: + raise amdsmi_cli_exceptions.AmdSmiInvalidParameterValueException(level, output_format) + perf_levels.append(level) + + clk_level_args = collections.namedtuple('clk_level_args', ['clk_type', 'perf_levels']) + setattr(namespace, self.dest, clk_level_args(clk_type, perf_levels)) + return AMDSMIFreqArgs + + def _check_output_file_path(self): """ Argument action validator: Returns a path to a file from the output file path provided. @@ -607,6 +638,10 @@ class AMDSMIParser(argparse.ArgumentParser): soc_pstate_help = "The available soc pstate policy" xgmi_plpd_help = "The available XGMI per-link power down policy" process_isolation_help = "The process isolation status" + clk_options = self.helpers.get_clock_types()[0] + clk_options.remove('PCIE') + clk_option_str = ", ".join(clk_options) + ", ALL" + clock_help = f"Show one or more valid clock frequency levels. Available options:\n\t{clk_option_str}" # Options arguments help text for Hypervisors and Baremetal ras_help = "Displays RAS features information" @@ -642,6 +677,7 @@ class AMDSMIParser(argparse.ArgumentParser): static_parser.add_argument('-B', '--board', action='store_true', required=False, help=board_help) static_parser.add_argument('-R', '--process-isolation', action='store_true', required=False, help=process_isolation_help) static_parser.add_argument('-r', '--ras', action='store_true', required=False, help=ras_help) + static_parser.add_argument('-C', '--clock', default=False, nargs='*', type=str, required=False, help=clock_help) # Options to display on Hypervisors and Baremetal if self.helpers.is_hypervisor() or self.helpers.is_baremetal(): @@ -1047,6 +1083,7 @@ class AMDSMIParser(argparse.ArgumentParser): set_soc_pstate_help = "Set the GPU soc pstate policy using policy id\n" set_xgmi_plpd_help = "Set the GPU XGMI per-link power down policy using policy id\n" set_clk_limit_help = "Sets the sclk (aka gfxclk) or mclk minimum and maximum frequencies:\n\tamd-smi set -L (sclk | mclk) (min | max) value" + set_clock_freq_help = "Set the sclk (aka gfxclk), mclk, fclk, pcie, or socclk frequency performance level.\nCan take range of acceptable levels." set_process_isolation_help = "Enable or disable the GPU process isolation on a per partition basis:\n\t0 for disable and 1 for enable.\n" # Help text for CPU set options @@ -1086,6 +1123,7 @@ class AMDSMIParser(argparse.ArgumentParser): set_value_parser.add_argument('-o', '--power-cap', action='store', type=self._positive_int, required=False, help=set_power_cap_help, metavar='WATTS') set_value_parser.add_argument('-p', '--soc-pstate', action='store', required=False, type=self._not_negative_int, help=set_soc_pstate_help, metavar='POLICY_ID') set_value_parser.add_argument('-x', '--xgmi-plpd', action='store', required=False, type=self._not_negative_int, help=set_xgmi_plpd_help, metavar='POLICY_ID') + set_value_parser.add_argument('-c', '--clk-level', action=self._level_select(), nargs='+', required=False, help=set_clock_freq_help, metavar=('CLK_TYPE', 'PERF_LEVELS')) set_value_parser.add_argument('-L', '--clk-limit', action=self._limit_select(), nargs=3, required=False, help=set_clk_limit_help, metavar=('CLK_TYPE', 'LIM_TYPE', 'VALUE')) set_value_parser.add_argument('-R', '--process-isolation', action='store', choices=[0,1], type=self._not_negative_int, required=False, help=set_process_isolation_help, metavar='STATUS') diff --git a/docs/how-to/amdsmi-cli-tool.md b/docs/how-to/amdsmi-cli-tool.md index 687d164ede..1f3589dec2 100644 --- a/docs/how-to/amdsmi-cli-tool.md +++ b/docs/how-to/amdsmi-cli-tool.md @@ -158,6 +158,8 @@ Static Arguments: -B, --board All board information -R, --process-isolation The process isolation status -r, --ras Displays RAS features information + -C, --clock [CLOCK ...] Show one or more valid clock frequency levels. Available options: + SYS, DF, DCEF, SOC, MEM, VCLK0, VCLK1, DCLK0, DCLK1, ALL -p, --partition Partition information -l, --limit All limit metric values (i.e. power and thermal limits) -P, --policy The available DPM policy @@ -538,6 +540,8 @@ Set Arguments: -o, --power-cap WATTS Set power capacity limit -p, --soc-pstate POLICY_ID Set the GPU soc pstate policy using policy id -x, --xgmi-plpd POLICY_ID Set the GPU XGMI per-link power down policy using policy id + -c, --clk-level CLK_TYPE [PERF_LEVELS ...] Set the sclk (aka gfxclk), mclk, fclk, pcie, or socclk frequency performance level. + Can take range of acceptable levels. -L, --clk-limit CLK_TYPE LIM_TYPE VALUE Sets the sclk (aka gfxclk) or mclk minimum and maximum frequencies amd-smi set -L (sclk | mclk) (min | max) value -R, --process-isolation STATUS Enable or disable the GPU process isolation: @@ -855,5 +859,35 @@ GPU: 0 CACHE_LEVEL: 3 MAX_NUM_CU_SHARED: 228 NUM_CACHE_INSTANCE: 1 + CLOCK: + SYS: + CURRENT LEVEL: 2 + FREQUENCY_LEVELS: + 0: 300 MHz + 1: 904 MHz + 2: 1165 MHz + 3: 1360 MHz + 4: 1440 MHz + 5: 1544 MHz + 6: 1627 MHz + 7: 1720 MHz + 8: 1800 MHz + DF: + CURRENT LEVEL: 0 + FREQUENCY_LEVELS: + 0: 1400 MHz + DCEF: N/A + SOC: + CURRENT LEVEL: 0 + FREQUENCY_LEVELS: + 0: 302 MHz + MEM: + CURRENT LEVEL: 0 + FREQUENCY_LEVELS: + 0: 167 MHz + VCLK0: N/A + VCLK1: N/A + DCLK1: N/A + DCLK0: N/A ... ``` diff --git a/example/amd_smi_drm_example.cc b/example/amd_smi_drm_example.cc index f006ac05f9..56050d6bb2 100644 --- a/example/amd_smi_drm_example.cc +++ b/example/amd_smi_drm_example.cc @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -262,11 +263,11 @@ int main() { ret = amdsmi_get_gpu_device_bdf(processor_handles[j], &bdf); CHK_AMDSMI_RET(ret) printf(" Output of amdsmi_get_gpu_device_bdf:\n"); - printf("\tDevice[%d] BDF %04lx:%02x:%02x.%d\n\n", i, - bdf.domain_number, - bdf.bus_number, - bdf.device_number, - bdf.function_number); + printf("\tDevice[%d] BDF %04" PRIx64 ":%02" PRIx32 ":%02" PRIx32 ".%" PRIu32 "\n\n", i, + static_cast(bdf.domain_number), + static_cast(bdf.bus_number), + static_cast(bdf.device_number), + static_cast(bdf.function_number)); // Get handle from BDF amdsmi_processor_handle dev_handle; @@ -408,12 +409,12 @@ int main() { printf("\tPCIe max speed: %d\n", pcie_info.pcie_static.max_pcie_speed); // additional pcie related metrics - printf("\tPCIe bandwidth: %d\n", pcie_info.pcie_metric.pcie_bandwidth); - printf("\tPCIe replay count: %d\n", pcie_info.pcie_metric.pcie_replay_count); - printf("\tPCIe L0 recovery count: %d\n", pcie_info.pcie_metric.pcie_l0_to_recovery_count); - printf("\tPCIe rollover count: %d\n", pcie_info.pcie_metric.pcie_replay_roll_over_count); - printf("\tPCIe nak received count: %d\n", pcie_info.pcie_metric.pcie_nak_received_count); - printf("\tPCIe nak sent count: %d\n", pcie_info.pcie_metric.pcie_nak_sent_count); + printf("\tPCIe bandwidth: %u\n", pcie_info.pcie_metric.pcie_bandwidth); + printf("\tPCIe replay count: %" PRIu64 "\n", pcie_info.pcie_metric.pcie_replay_count); + printf("\tPCIe L0 recovery count: %" PRIu64 "\n", pcie_info.pcie_metric.pcie_l0_to_recovery_count); + printf("\tPCIe rollover count: %" PRIu64 "\n", pcie_info.pcie_metric.pcie_replay_roll_over_count); + printf("\tPCIe nak received count: %" PRIu64 "\n", pcie_info.pcie_metric.pcie_nak_received_count); + printf("\tPCIe nak sent count: %" PRIu64 "\n", pcie_info.pcie_metric.pcie_nak_sent_count); // Get VRAM temperature limit int64_t temperature = 0; @@ -522,13 +523,6 @@ int main() { printf("\tCorrectable errors: %lu\n", err_cnt_info.correctable_count); printf("\tUncorrectable errors: %lu\n\n", err_cnt_info.uncorrectable_count); - // Get process list - auto compare = [](const void *a, const void *b) -> int { - return (*(amdsmi_proc_info_t *)a).pid > - (*(amdsmi_proc_info_t *)b).pid - ? 1 - : -1; - }; uint32_t num_process = 0; ret = amdsmi_get_gpu_process_list(processor_handles[j], &num_process, nullptr); @@ -542,18 +536,17 @@ int main() { uint64_t mem = 0, gtt_mem = 0, cpu_mem = 0, vram_mem = 0; uint64_t gfx = 0, enc = 0; char bdf_str[20]; - sprintf(bdf_str, "%04lx:%02x:%02x.%d", - bdf.domain_number, - bdf.bus_number, - bdf.device_number, - bdf.function_number); - int num = 0; + sprintf(bdf_str, "%04" PRIx64 ":%02" PRIx32 ":%02" PRIx32 ".%" PRIu32, + static_cast(bdf.domain_number), + static_cast(bdf.bus_number), + static_cast(bdf.device_number), + static_cast(bdf.function_number)); ret = amdsmi_get_gpu_process_list(processor_handles[j], &num_process, process_info_list); std::cout << "Allocation size for process list: " << num_process << "\n"; CHK_AMDSMI_RET(ret); for (auto idx = uint32_t(0); idx < num_process; ++idx) { process = static_cast(process_info_list[idx]); - printf("\t *Process id: %ld / Name: %s / VRAM: %lld \n", process.pid, process.name, process.memory_usage.vram_mem); + printf("\t *Process id: %d / Name: %s / VRAM: %ld \n", process.pid, process.name, process.memory_usage.vram_mem); } printf("+=======+==================+============+==============" @@ -569,7 +562,7 @@ int main() { printf("+=======+" "+=============+=============+=============+============" "==+=========================================+\n"); - for (int it = 0; it < num_process; it++) { + for (int it = 0; it < static_cast(num_process); it++) { char command[30]; struct passwd *pwd = nullptr; struct stat st; @@ -609,11 +602,13 @@ int main() { "-+-------------+-------------+-------------+----------" "----+-----------------------------------------+\n"); } + // TODO: To remove compiler warning, the last 3 values in this printf were + // set to 0L. Need to find out what these values need to be. printf("| TOTAL:| %s | %7ld " "KiB | %7ld KiB | %7ld KiB | %7ld KiB | %lu %lu " "%lu %lu %lu |\n", bdf_str, mem, gtt_mem, cpu_mem, vram_mem, gfx, - enc); + enc, 0L, 0L, 0L); printf("+=======+==================+============+==============" "+=============+=============+=============+============" "=+==========================================+\n"); @@ -674,11 +669,11 @@ int main() { ret = amdsmi_get_gpu_metrics_info(processor_handles[j], &smu); CHK_AMDSMI_RET(ret) printf(" Output of amdsmi_get_gpu_metrics_info:\n"); - printf("\tDevice[%d] BDF %04lx:%02x:%02x.%d\n\n", i, - bdf.domain_number, - bdf.bus_number, - bdf.device_number, - bdf.function_number); + printf("\tDevice[%d] BDF %04" PRIx64 ":%02" PRIx32 ":%02" PRIx32 ".%" PRIu32 "\n\n", i, + static_cast(bdf.domain_number), + static_cast(bdf.bus_number), + static_cast(bdf.device_number), + static_cast(bdf.function_number)); std::cout << "METRIC TABLE HEADER:\n"; std::cout << "structure_size=" << std::dec @@ -706,7 +701,7 @@ int main() { auto idx = 0; for (const auto& temp : smu.temperature_hbm) { std::cout << temp; - if ((idx + 1) != std::size(smu.temperature_hbm)) { + if ((idx + 1) != static_cast(std::size(smu.temperature_hbm))) { std::cout << ", "; } else { std::cout << "]\n"; @@ -723,7 +718,7 @@ int main() { idx = 0; for (const auto& temp : smu.vcn_activity) { std::cout << temp; - if ((idx + 1) != std::size(smu.vcn_activity)) { + if ((idx + 1) != static_cast(std::size(smu.vcn_activity))) { std::cout << ", "; } else { std::cout << "]\n"; @@ -736,7 +731,7 @@ int main() { idx = 0; for (const auto& temp : smu.jpeg_activity) { std::cout << temp; - if ((idx + 1) != std::size(smu.jpeg_activity)) { + if ((idx + 1) != static_cast(std::size(smu.jpeg_activity))) { std::cout << ", "; } else { std::cout << "]\n"; @@ -773,7 +768,7 @@ int main() { idx = 0; for (const auto& temp : smu.current_gfxclks) { std::cout << temp; - if ((idx + 1) != std::size(smu.current_gfxclks)) { + if ((idx + 1) != static_cast(std::size(smu.current_gfxclks))) { std::cout << ", "; } else { std::cout << "]\n"; @@ -786,7 +781,7 @@ int main() { idx = 0; for (const auto& temp : smu.current_socclks) { std::cout << temp; - if ((idx + 1) != std::size(smu.current_socclks)) { + if ((idx + 1) != static_cast(std::size(smu.current_socclks))) { std::cout << ", "; } else { std::cout << "]\n"; @@ -800,7 +795,7 @@ int main() { idx = 0; for (const auto& temp : smu.current_vclk0s) { std::cout << temp; - if ((idx + 1) != std::size(smu.current_vclk0s)) { + if ((idx + 1) != static_cast(std::size(smu.current_vclk0s))) { std::cout << ", "; } else { std::cout << "]\n"; @@ -813,7 +808,7 @@ int main() { idx = 0; for (const auto& temp : smu.current_dclk0s) { std::cout << temp; - if ((idx + 1) != std::size(smu.current_dclk0s)) { + if ((idx + 1) != static_cast(std::size(smu.current_dclk0s))) { std::cout << ", "; } else { std::cout << "]\n"; @@ -850,7 +845,7 @@ int main() { idx = 0; for (const auto& temp : smu.xgmi_read_data_acc) { std::cout << temp; - if ((idx + 1) != std::size(smu.xgmi_read_data_acc)) { + if ((idx + 1) != static_cast(std::size(smu.xgmi_read_data_acc))) { std::cout << ", "; } else { std::cout << "]\n"; @@ -862,7 +857,7 @@ int main() { idx = 0; for (const auto& temp : smu.xgmi_write_data_acc) { std::cout << temp; - if ((idx + 1) != std::size(smu.xgmi_write_data_acc)) { + if ((idx + 1) != static_cast(std::size(smu.xgmi_write_data_acc))) { std::cout << ", "; } else { std::cout << "]\n"; @@ -922,7 +917,7 @@ int main() { for (auto& row : smu.xcp_stats) { std::cout << "\t XCP [" << idx << "] : ["; for (auto& col : row.gfx_busy_inst) { - if ((idy + 1) != std::size(row.gfx_busy_inst)) { + if ((idy + 1) != static_cast(std::size(row.gfx_busy_inst))) { std::cout << col << ", "; } else { std::cout << col; @@ -940,7 +935,7 @@ int main() { for (auto& row : smu.xcp_stats) { std::cout << "\t XCP [" << idx << "] : ["; for (auto& col : row.vcn_busy) { - if ((idy + 1) != std::size(row.vcn_busy)) { + if ((idy + 1) != static_cast(std::size(row.vcn_busy))) { std::cout << col << ", "; } else { std::cout << col; @@ -958,7 +953,7 @@ int main() { for (auto& row : smu.xcp_stats) { std::cout << "\t XCP [" << idx << "] : ["; for (auto& col : row.jpeg_busy) { - if ((idy + 1) != std::size(row.jpeg_busy)) { + if ((idy + 1) != static_cast(std::size(row.jpeg_busy))) { std::cout << col << ", "; } else { std::cout << col; @@ -976,7 +971,7 @@ int main() { for (auto& row : smu.xcp_stats) { std::cout << "\t XCP [" << idx << "] : ["; for (auto& col : row.gfx_busy_acc) { - if ((idy + 1) != std::size(row.gfx_busy_acc)) { + if ((idy + 1) != static_cast(std::size(row.gfx_busy_acc))) { std::cout << col << ", "; } else { std::cout << col; @@ -1040,8 +1035,11 @@ int main() { amdsmi_bdf_t bdf = {}; ret = amdsmi_get_gpu_device_bdf(topology_nearest_info.processor_list[k], &bdf); CHK_AMDSMI_RET(ret) - printf("\t\tGPU BDF %04lx:%02x:%02x.%d\n", bdf.domain_number, - bdf.bus_number, bdf.device_number, bdf.function_number); + printf("\t\tGPU BDF %04" PRIx64 ":%02" PRIx32 ":%02" PRIx32 ".%" PRIu32 "\n", + static_cast(bdf.domain_number), + static_cast(bdf.bus_number), + static_cast(bdf.device_number), + static_cast(bdf.function_number)); } } } diff --git a/example/amd_smi_nodrm_example.cc b/example/amd_smi_nodrm_example.cc index bdcca88838..583af1a178 100644 --- a/example/amd_smi_nodrm_example.cc +++ b/example/amd_smi_nodrm_example.cc @@ -21,6 +21,7 @@ */ #include +#include #include #include @@ -114,11 +115,11 @@ int main() { ret = amdsmi_get_gpu_device_bdf(processor_handles[j], &bdf); CHK_AMDSMI_RET(ret) printf(" Output of amdsmi_get_gpu_device_bdf:\n"); - printf("\tDevice[%d] BDF %04lx:%02x:%02x.%d\n\n", i, - bdf.domain_number, - bdf.bus_number, - bdf.device_number, - bdf.function_number); + printf("\tDevice[%d] BDF %04" PRIx64 ":%02" PRIx32 ":%02" PRIx32 ".%" PRIu32 "\n\n", i, + static_cast(bdf.domain_number), + static_cast(bdf.bus_number), + static_cast(bdf.device_number), + static_cast(bdf.function_number)); amdsmi_asic_info_t asic_info = {}; ret = amdsmi_get_gpu_asic_info(processor_handles[j], &asic_info); @@ -319,7 +320,7 @@ int main() { CHK_AMDSMI_RET(ret) std::cout << "\t amdsmi_get_soc_pstate total:" << policy.num_supported <<" current:" << policy.current << "\n"; - for (int x=0; x < policy.num_supported; x++) { + for (uint32_t x=0; x < policy.num_supported; x++) { std::cout << x <<": (" << policy.policies[x].policy_id <<"," << policy.policies[x].policy_description << ")\n"; } @@ -349,8 +350,11 @@ int main() { amdsmi_bdf_t bdf = {}; ret = amdsmi_get_gpu_device_bdf(topology_nearest_info.processor_list[k], &bdf); CHK_AMDSMI_RET(ret) - printf("\tGPU BDF %04lx:%02x:%02x.%d\n", bdf.domain_number, - bdf.bus_number, bdf.device_number, bdf.function_number); + printf("\tGPU BDF %04" PRIx64 ":%02" PRIx32 ":%02" PRIx32 ".%" PRIu32 "\n", + static_cast(bdf.domain_number), + static_cast(bdf.bus_number), + static_cast(bdf.device_number), + static_cast(bdf.function_number)); } } } diff --git a/example/amdsmi_esmi_intg_example.cc b/example/amdsmi_esmi_intg_example.cc index 5f24eb27d0..ea156484ac 100644 --- a/example/amdsmi_esmi_intg_example.cc +++ b/example/amdsmi_esmi_intg_example.cc @@ -54,7 +54,7 @@ using std::fixed; using std::setprecision; using std::vector; -int main(int argc, char **argv) { +int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) { amdsmi_status_t ret; uint32_t proto_ver; amdsmi_smu_fw_version_t smu_fw = {}; @@ -157,7 +157,7 @@ int main(int argc, char **argv) { retVal = snprintf(str, SHOWLINESZ, "\n| mclk (Mhz)\t\t\t |"); len = strlen(str); - uint32_t fclk, mclk, cclk; + uint32_t fclk, mclk; err_bits = 0; ret = amdsmi_get_cpu_fclk_mclk(plist[index], &fclk, &mclk); @@ -265,7 +265,6 @@ int main(int argc, char **argv) { double fraction_q10 = 1/pow(2,10); double fraction_uq10 = fraction_q10; - const char* err_str1; amdsmi_hsmp_metrics_table_t mtbl = {}; ret = amdsmi_get_hsmp_metrics_table(plist[index], &mtbl); diff --git a/include/amd_smi/amdsmi.h b/include/amd_smi/amdsmi.h index 1b17643ef9..e27b255007 100644 --- a/include/amd_smi/amdsmi.h +++ b/include/amd_smi/amdsmi.h @@ -961,7 +961,8 @@ typedef enum { #define AMDSMI_EVENT_MASK_FROM_INDEX(i) (1ULL << ((i) - 1)) //! Maximum number of characters an event notification message will be -#define MAX_EVENT_NOTIFICATION_MSG_SIZE 64 +// matches kfd message max size +#define MAX_EVENT_NOTIFICATION_MSG_SIZE 96 /** * Event notification data returned from event notification API @@ -1415,7 +1416,7 @@ typedef struct { /** * @brief The following structures hold the gpu statistics for a device. */ -struct amdsmi_gpu_xcp_metrics_t { +typedef struct { /* Utilization Instantaneous (%) */ uint32_t gfx_busy_inst[AMDSMI_MAX_NUM_XCC]; uint16_t jpeg_busy[AMDSMI_MAX_NUM_JPEG]; @@ -1423,7 +1424,7 @@ struct amdsmi_gpu_xcp_metrics_t { /* Utilization Accumulated (%) */ uint64_t gfx_busy_acc[AMDSMI_MAX_NUM_XCC]; -}; +} amdsmi_gpu_xcp_metrics_t; typedef struct { @@ -1622,7 +1623,7 @@ typedef struct { uint16_t num_partition; /* XCP (Graphic Cluster Partitions) metrics stats */ - struct amdsmi_gpu_xcp_metrics_t xcp_stats[AMDSMI_MAX_NUM_XCP]; + amdsmi_gpu_xcp_metrics_t xcp_stats[AMDSMI_MAX_NUM_XCP]; /* PCIE other end recovery counter */ uint32_t pcie_lc_perf_other_end_recovery; diff --git a/include/amd_smi/impl/amd_hsmp.h b/include/amd_smi/impl/amd_hsmp.h new file mode 100644 index 0000000000..b027cec2ad --- /dev/null +++ b/include/amd_smi/impl/amd_hsmp.h @@ -0,0 +1,417 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ + +#ifndef _UAPI_ASM_X86_AMD_HSMP_H_ +#define _UAPI_ASM_X86_AMD_HSMP_H_ + +#include + +#pragma pack(4) + +#define HSMP_MAX_MSG_LEN 8 + +/* + * HSMP Messages supported + */ +enum hsmp_message_ids { + HSMP_TEST = 1, /* 01h Increments input value by 1 */ + HSMP_GET_SMU_VER, /* 02h SMU FW version */ + HSMP_GET_PROTO_VER, /* 03h HSMP interface version */ + HSMP_GET_SOCKET_POWER, /* 04h average package power consumption */ + HSMP_SET_SOCKET_POWER_LIMIT, /* 05h Set the socket power limit */ + HSMP_GET_SOCKET_POWER_LIMIT, /* 06h Get current socket power limit */ + HSMP_GET_SOCKET_POWER_LIMIT_MAX,/* 07h Get maximum socket power value */ + HSMP_SET_BOOST_LIMIT, /* 08h Set a core maximum frequency limit */ + HSMP_SET_BOOST_LIMIT_SOCKET, /* 09h Set socket maximum frequency level */ + HSMP_GET_BOOST_LIMIT, /* 0Ah Get current frequency limit */ + HSMP_GET_PROC_HOT, /* 0Bh Get PROCHOT status */ + HSMP_SET_XGMI_LINK_WIDTH, /* 0Ch Set max and min width of xGMI Link */ + HSMP_SET_DF_PSTATE, /* 0Dh Alter APEnable/Disable messages behavior */ + HSMP_SET_AUTO_DF_PSTATE, /* 0Eh Enable DF P-State Performance Boost algorithm */ + HSMP_GET_FCLK_MCLK, /* 0Fh Get FCLK and MEMCLK for current socket */ + HSMP_GET_CCLK_THROTTLE_LIMIT, /* 10h Get CCLK frequency limit in socket */ + HSMP_GET_C0_PERCENT, /* 11h Get average C0 residency in socket */ + HSMP_SET_NBIO_DPM_LEVEL, /* 12h Set max/min LCLK DPM Level for a given NBIO */ + HSMP_GET_NBIO_DPM_LEVEL, /* 13h Get LCLK DPM level min and max for a given NBIO */ + HSMP_GET_DDR_BANDWIDTH, /* 14h Get theoretical maximum and current DDR Bandwidth */ + HSMP_GET_TEMP_MONITOR, /* 15h Get socket temperature */ + HSMP_GET_DIMM_TEMP_RANGE, /* 16h Get per-DIMM temperature range and refresh rate */ + HSMP_GET_DIMM_POWER, /* 17h Get per-DIMM power consumption */ + HSMP_GET_DIMM_THERMAL, /* 18h Get per-DIMM thermal sensors */ + HSMP_GET_SOCKET_FREQ_LIMIT, /* 19h Get current active frequency per socket */ + HSMP_GET_CCLK_CORE_LIMIT, /* 1Ah Get CCLK frequency limit per core */ + HSMP_GET_RAILS_SVI, /* 1Bh Get SVI-based Telemetry for all rails */ + HSMP_GET_SOCKET_FMAX_FMIN,/* 1Ch Get Fmax and Fmin per socket */ + HSMP_GET_IOLINK_BANDWITH, /* 1Dh Get current bandwidth on IO Link */ + HSMP_GET_XGMI_BANDWITH, /* 1Eh Get current bandwidth on xGMI Link */ + HSMP_SET_GMI3_WIDTH, /* 1Fh Set max and min GMI3 Link width */ + HSMP_SET_PCI_RATE, /* 20h Control link rate on PCIe devices */ + HSMP_SET_POWER_MODE, /* 21h Select power efficiency profile policy */ + HSMP_SET_PSTATE_MAX_MIN, /* 22h Set the max and min DF P-State */ + HSMP_GET_METRIC_TABLE_VER,/* 23h Get metrics table version */ + HSMP_GET_METRIC_TABLE, /* 24h Get metrics table */ + HSMP_GET_METRIC_TABLE_DRAM_ADDR,/* 25h Get metrics table dram address */ + HSMP_MSG_ID_MAX, +}; + +struct hsmp_message { + __u32 msg_id; /* Message ID */ + __u16 num_args; /* Number of input argument words in message */ + __u16 response_sz; /* Number of expected output/response words */ + __u32 args[HSMP_MAX_MSG_LEN]; /* argument/response buffer */ + __u16 sock_ind; /* socket number */ +}; + +enum hsmp_msg_type { + HSMP_RSVD = -1, + HSMP_SET = 0, + HSMP_GET = 1, +}; + +enum hsmp_proto_versions { + HSMP_PROTO_VER2 = 2, + HSMP_PROTO_VER3, + HSMP_PROTO_VER4, + HSMP_PROTO_VER5, + HSMP_PROTO_VER6 +}; + +struct hsmp_msg_desc { + int num_args; + int response_sz; + enum hsmp_msg_type type; +}; + +/* + * User may use these comments as reference, please find the + * supported list of messages and message definition in the + * HSMP chapter of respective family/model PPR. + * + * Not supported messages would return -ENOMSG. + */ +static const struct hsmp_msg_desc hsmp_msg_desc_table[] + __attribute__((unused)) = { + /* RESERVED */ + {0, 0, HSMP_RSVD}, + + /* + * HSMP_TEST, num_args = 1, response_sz = 1 + * input: args[0] = xx + * output: args[0] = xx + 1 + */ + {1, 1, HSMP_GET}, + + /* + * HSMP_GET_SMU_VER, num_args = 0, response_sz = 1 + * output: args[0] = smu fw ver + */ + {0, 1, HSMP_GET}, + + /* + * HSMP_GET_PROTO_VER, num_args = 0, response_sz = 1 + * output: args[0] = proto version + */ + {0, 1, HSMP_GET}, + + /* + * HSMP_GET_SOCKET_POWER, num_args = 0, response_sz = 1 + * output: args[0] = socket power in mWatts + */ + {0, 1, HSMP_GET}, + + /* + * HSMP_SET_SOCKET_POWER_LIMIT, num_args = 1, response_sz = 0 + * input: args[0] = power limit value in mWatts + */ + {1, 0, HSMP_SET}, + + /* + * HSMP_GET_SOCKET_POWER_LIMIT, num_args = 0, response_sz = 1 + * output: args[0] = socket power limit value in mWatts + */ + {0, 1, HSMP_GET}, + + /* + * HSMP_GET_SOCKET_POWER_LIMIT_MAX, num_args = 0, response_sz = 1 + * output: args[0] = maximuam socket power limit in mWatts + */ + {0, 1, HSMP_GET}, + + /* + * HSMP_SET_BOOST_LIMIT, num_args = 1, response_sz = 0 + * input: args[0] = apic id[31:16] + boost limit value in MHz[15:0] + */ + {1, 0, HSMP_SET}, + + /* + * HSMP_SET_BOOST_LIMIT_SOCKET, num_args = 1, response_sz = 0 + * input: args[0] = boost limit value in MHz + */ + {1, 0, HSMP_SET}, + + /* + * HSMP_GET_BOOST_LIMIT, num_args = 1, response_sz = 1 + * input: args[0] = apic id + * output: args[0] = boost limit value in MHz + */ + {1, 1, HSMP_GET}, + + /* + * HSMP_GET_PROC_HOT, num_args = 0, response_sz = 1 + * output: args[0] = proc hot status + */ + {0, 1, HSMP_GET}, + + /* + * HSMP_SET_XGMI_LINK_WIDTH, num_args = 1, response_sz = 0 + * input: args[0] = min link width[15:8] + max link width[7:0] + */ + {1, 0, HSMP_SET}, + + /* + * HSMP_SET_DF_PSTATE, num_args = 1, response_sz = 0 + * input: args[0] = df pstate[7:0] + */ + {1, 0, HSMP_SET}, + + /* HSMP_SET_AUTO_DF_PSTATE, num_args = 0, response_sz = 0 */ + {0, 0, HSMP_SET}, + + /* + * HSMP_GET_FCLK_MCLK, num_args = 0, response_sz = 2 + * output: args[0] = fclk in MHz, args[1] = mclk in MHz + */ + {0, 2, HSMP_GET}, + + /* + * HSMP_GET_CCLK_THROTTLE_LIMIT, num_args = 0, response_sz = 1 + * output: args[0] = core clock in MHz + */ + {0, 1, HSMP_GET}, + + /* + * HSMP_GET_C0_PERCENT, num_args = 0, response_sz = 1 + * output: args[0] = average c0 residency + */ + {0, 1, HSMP_GET}, + + /* + * HSMP_SET_NBIO_DPM_LEVEL, num_args = 1, response_sz = 0 + * input: args[0] = nbioid[23:16] + max dpm level[15:8] + min dpm level[7:0] + */ + {1, 0, HSMP_SET}, + + /* + * HSMP_GET_NBIO_DPM_LEVEL, num_args = 1, response_sz = 1 + * input: args[0] = nbioid[23:16] + * output: args[0] = max dpm level[15:8] + min dpm level[7:0] + */ + {1, 1, HSMP_GET}, + + /* + * HSMP_GET_DDR_BANDWIDTH, num_args = 0, response_sz = 1 + * output: args[0] = max bw in Gbps[31:20] + utilised bw in Gbps[19:8] + + * bw in percentage[7:0] + */ + {0, 1, HSMP_GET}, + + /* + * HSMP_GET_TEMP_MONITOR, num_args = 0, response_sz = 1 + * output: args[0] = temperature in degree celsius. [15:8] integer part + + * [7:5] fractional part + */ + {0, 1, HSMP_GET}, + + /* + * HSMP_GET_DIMM_TEMP_RANGE, num_args = 1, response_sz = 1 + * input: args[0] = DIMM address[7:0] + * output: args[0] = refresh rate[3] + temperature range[2:0] + */ + {1, 1, HSMP_GET}, + + /* + * HSMP_GET_DIMM_POWER, num_args = 1, response_sz = 1 + * input: args[0] = DIMM address[7:0] + * output: args[0] = DIMM power in mW[31:17] + update rate in ms[16:8] + + * DIMM address[7:0] + */ + {1, 1, HSMP_GET}, + + /* + * HSMP_GET_DIMM_THERMAL, num_args = 1, response_sz = 1 + * input: args[0] = DIMM address[7:0] + * output: args[0] = temperature in degree celsius[31:21] + update rate in ms[16:8] + + * DIMM address[7:0] + */ + {1, 1, HSMP_GET}, + + /* + * HSMP_GET_SOCKET_FREQ_LIMIT, num_args = 0, response_sz = 1 + * output: args[0] = frequency in MHz[31:16] + frequency source[15:0] + */ + {0, 1, HSMP_GET}, + + /* + * HSMP_GET_CCLK_CORE_LIMIT, num_args = 1, response_sz = 1 + * input: args[0] = apic id [31:0] + * output: args[0] = frequency in MHz[31:0] + */ + {1, 1, HSMP_GET}, + + /* + * HSMP_GET_RAILS_SVI, num_args = 0, response_sz = 1 + * output: args[0] = power in mW[31:0] + */ + {0, 1, HSMP_GET}, + + /* + * HSMP_GET_SOCKET_FMAX_FMIN, num_args = 0, response_sz = 1 + * output: args[0] = fmax in MHz[31:16] + fmin in MHz[15:0] + */ + {0, 1, HSMP_GET}, + + /* + * HSMP_GET_IOLINK_BANDWITH, num_args = 1, response_sz = 1 + * input: args[0] = link id[15:8] + bw type[2:0] + * output: args[0] = io bandwidth in Mbps[31:0] + */ + {1, 1, HSMP_GET}, + + /* + * HSMP_GET_XGMI_BANDWITH, num_args = 1, response_sz = 1 + * input: args[0] = link id[15:8] + bw type[2:0] + * output: args[0] = xgmi bandwidth in Mbps[31:0] + */ + {1, 1, HSMP_GET}, + + /* + * HSMP_SET_GMI3_WIDTH, num_args = 1, response_sz = 0 + * input: args[0] = min link width[15:8] + max link width[7:0] + */ + {1, 0, HSMP_SET}, + + /* + * HSMP_SET_PCI_RATE, num_args = 1, response_sz = 1 + * input: args[0] = link rate control value + * output: args[0] = previous link rate control value + */ + {1, 1, HSMP_SET}, + + /* + * HSMP_SET_POWER_MODE, num_args = 1, response_sz = 0 + * input: args[0] = power efficiency mode[2:0] + */ + {1, 0, HSMP_SET}, + + /* + * HSMP_SET_PSTATE_MAX_MIN, num_args = 1, response_sz = 0 + * input: args[0] = min df pstate[15:8] + max df pstate[7:0] + */ + {1, 0, HSMP_SET}, + + /* + * HSMP_GET_METRIC_TABLE_VER, num_args = 0, response_sz = 1 + * output: args[0] = metrics table version + */ + {0, 1, HSMP_GET}, + + /* + * HSMP_GET_METRIC_TABLE, num_args = 0, response_sz = 0 + */ + {0, 0, HSMP_GET}, + + /* + * HSMP_GET_METRIC_TABLE_DRAM_ADDR, num_args = 0, response_sz = 2 + * output: args[0] = lower 32 bits of the address + * output: args[1] = upper 32 bits of the address + */ + {0, 2, HSMP_GET}, +}; + +/* Metrics table (supported only with proto version 6) */ +struct hsmp_metric_table { + __u32 accumulation_counter; + + /* TEMPERATURE */ + __u32 max_socket_temperature; + __u32 max_vr_temperature; + __u32 max_hbm_temperature; + __u64 max_socket_temperature_acc; + __u64 max_vr_temperature_acc; + __u64 max_hbm_temperature_acc; + + /* POWER */ + __u32 socket_power_limit; + __u32 max_socket_power_limit; + __u32 socket_power; + + /* ENERGY */ + __u64 timestamp; + __u64 socket_energy_acc; + __u64 ccd_energy_acc; + __u64 xcd_energy_acc; + __u64 aid_energy_acc; + __u64 hbm_energy_acc; + + /* FREQUENCY */ + __u32 cclk_frequency_limit; + __u32 gfxclk_frequency_limit; + __u32 fclk_frequency; + __u32 uclk_frequency; + __u32 socclk_frequency[4]; + __u32 vclk_frequency[4]; + __u32 dclk_frequency[4]; + __u32 lclk_frequency[4]; + __u64 gfxclk_frequency_acc[8]; + __u64 cclk_frequency_acc[96]; + + /* FREQUENCY RANGE */ + __u32 max_cclk_frequency; + __u32 min_cclk_frequency; + __u32 max_gfxclk_frequency; + __u32 min_gfxclk_frequency; + __u32 fclk_frequency_table[4]; + __u32 uclk_frequency_table[4]; + __u32 socclk_frequency_table[4]; + __u32 vclk_frequency_table[4]; + __u32 dclk_frequency_table[4]; + __u32 lclk_frequency_table[4]; + __u32 max_lclk_dpm_range; + __u32 min_lclk_dpm_range; + + /* XGMI */ + __u32 xgmi_width; + __u32 xgmi_bitrate; + __u64 xgmi_read_bandwidth_acc[8]; + __u64 xgmi_write_bandwidth_acc[8]; + + /* ACTIVITY */ + __u32 socket_c0_residency; + __u32 socket_gfx_busy; + __u32 dram_bandwidth_utilization; + __u64 socket_c0_residency_acc; + __u64 socket_gfx_busy_acc; + __u64 dram_bandwidth_acc; + __u32 max_dram_bandwidth; + __u64 dram_bandwidth_utilization_acc; + __u64 pcie_bandwidth_acc[4]; + + /* THROTTLERS */ + __u32 prochot_residency_acc; + __u32 ppt_residency_acc; + __u32 socket_thm_residency_acc; + __u32 vr_thm_residency_acc; + __u32 hbm_thm_residency_acc; + __u32 spare; + + /* New items at the end to maintain driver compatibility */ + __u32 gfxclk_frequency[8]; +}; + +/* Reset to default packing */ +#pragma pack() + +/* Define unique ioctl command for hsmp msgs using generic _IOWR */ +#define HSMP_BASE_IOCTL_NR 0xF8 +#define HSMP_IOCTL_CMD _IOWR(HSMP_BASE_IOCTL_NR, 0, struct hsmp_message) + +#endif /*_ASM_X86_AMD_HSMP_H_*/ diff --git a/py-interface/amdsmi_interface.py b/py-interface/amdsmi_interface.py index 2c4a6b46ba..1a809a0fe6 100644 --- a/py-interface/amdsmi_interface.py +++ b/py-interface/amdsmi_interface.py @@ -69,7 +69,7 @@ AMDSMI_MAX_CACHE_TYPES = 10 AMDSMI_MAX_NUM_XGMI_PHYSICAL_LINK = 64 AMDSMI_GPU_UUID_SIZE = 38 MAX_AMDSMI_NAME_LENGTH = 64 -MAX_EVENT_NOTIFICATION_MSG_SIZE = 64 +MAX_EVENT_NOTIFICATION_MSG_SIZE = 96 class AmdSmiInitFlags(IntEnum): @@ -1653,7 +1653,7 @@ def amdsmi_get_gpu_asic_info( market_name = _pad_hex_value(asic_info_struct.market_name.decode("utf-8"), 4) target_graphics_version = str(asic_info_struct.target_graphics_version) - if len(target_graphics_version) == 4 and ("Instinct MI2" in market_name): + if target_graphics_version == "9010": hex_part = str(hex(int(str(asic_info_struct.target_graphics_version)[2:]))).replace("0x", "") target_graphics_version = str(asic_info_struct.target_graphics_version)[:2] + hex_part asic_info = { @@ -2956,21 +2956,31 @@ def amdsmi_reset_gpu_fan( def amdsmi_set_clk_freq( processor_handle: amdsmi_wrapper.amdsmi_processor_handle, - clk_type: AmdSmiClkType, + clk_type: str, freq_bitmask: int, ): if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle): raise AmdSmiParameterException( processor_handle, amdsmi_wrapper.amdsmi_processor_handle ) - if not isinstance(clk_type, AmdSmiClkType): - raise AmdSmiParameterException(clk_type, AmdSmiParameterException) + if clk_type.lower() == "sclk": + clk_type_conversion = AmdSmiClkType.SYS + elif clk_type.lower() == "mclk": + clk_type_conversion = AmdSmiClkType.MEM + elif clk_type.lower() == "fclk": + clk_type_conversion = AmdSmiClkType.DF + elif clk_type.lower() == "socclk": + clk_type_conversion = AmdSmiClkType.SOC + else: + clk_type_conversion = "N/A" + if not isinstance(clk_type_conversion, AmdSmiClkType): + raise AmdSmiParameterException(clk_type_conversion, AmdSmiClkType) if not isinstance(freq_bitmask, int): raise AmdSmiParameterException(freq_bitmask, int) freq_bitmask = ctypes.c_uint64(freq_bitmask) _check_res( amdsmi_wrapper.amdsmi_set_clk_freq( - processor_handle, clk_type, freq_bitmask + processor_handle, clk_type_conversion, freq_bitmask ) ) diff --git a/py-interface/amdsmi_wrapper.py b/py-interface/amdsmi_wrapper.py index c65800da99..e1513cdbb7 100644 --- a/py-interface/amdsmi_wrapper.py +++ b/py-interface/amdsmi_wrapper.py @@ -1300,7 +1300,7 @@ struct_amdsmi_evt_notification_data_t._pack_ = 1 # source:False struct_amdsmi_evt_notification_data_t._fields_ = [ ('processor_handle', ctypes.POINTER(None)), ('event', amdsmi_evt_notification_type_t), - ('message', ctypes.c_char * 64), + ('message', ctypes.c_char * 96), ('PADDING_0', ctypes.c_ubyte * 4), ] @@ -1741,6 +1741,7 @@ struct_amdsmi_gpu_xcp_metrics_t._fields_ = [ ('gfx_busy_acc', ctypes.c_uint64 * 8), ] +amdsmi_gpu_xcp_metrics_t = struct_amdsmi_gpu_xcp_metrics_t class struct_amdsmi_gpu_metrics_t(Structure): pass @@ -2869,11 +2870,12 @@ __all__ = \ 'amdsmi_gpu_cache_info_t', 'amdsmi_gpu_control_counter', 'amdsmi_gpu_counter_group_supported', 'amdsmi_gpu_create_counter', 'amdsmi_gpu_destroy_counter', 'amdsmi_gpu_metrics_t', - 'amdsmi_gpu_read_counter', 'amdsmi_gpu_xgmi_error_status', - 'amdsmi_hsmp_freqlimit_src_names', 'amdsmi_hsmp_metrics_table_t', - 'amdsmi_init', 'amdsmi_init_flags_t', - 'amdsmi_init_gpu_event_notification', 'amdsmi_io_bw_encoding_t', - 'amdsmi_io_link_type_t', 'amdsmi_is_P2P_accessible', + 'amdsmi_gpu_read_counter', 'amdsmi_gpu_xcp_metrics_t', + 'amdsmi_gpu_xgmi_error_status', 'amdsmi_hsmp_freqlimit_src_names', + 'amdsmi_hsmp_metrics_table_t', 'amdsmi_init', + 'amdsmi_init_flags_t', 'amdsmi_init_gpu_event_notification', + 'amdsmi_io_bw_encoding_t', 'amdsmi_io_link_type_t', + 'amdsmi_is_P2P_accessible', 'amdsmi_is_gpu_power_management_enabled', 'amdsmi_kfd_info_t', 'amdsmi_link_id_bw_type_t', 'amdsmi_link_metrics_t', 'amdsmi_link_type_t', 'amdsmi_memory_page_status_t', diff --git a/py-interface/pyproject.toml.in b/py-interface/pyproject.toml.in index 507faea358..93185b27e1 100644 --- a/py-interface/pyproject.toml.in +++ b/py-interface/pyproject.toml.in @@ -15,9 +15,6 @@ license = {file = "amdsmi/LICENSE"} readme = {file = "amdsmi/README.md", content-type = "text/markdown"} description = "AMDSMI Python LIB - AMD GPU Monitoring Library" requires-python = ">=3.6" -dependencies = [ - "PyYAML >= 3.0", -] classifiers = [ "Programming Language :: Python :: 3" ] diff --git a/py-interface/setup.py.in b/py-interface/setup.py.in index 8aa2091a78..eb3e992f65 100644 --- a/py-interface/setup.py.in +++ b/py-interface/setup.py.in @@ -9,9 +9,6 @@ setup( description="AMDSMI Python LIB - AMD GPU Monitoring Library", url="https://github.com/ROCm/amdsmi", packages=find_packages(), - install_requires=[ - "PyYAML>=3.0", - ], classifiers=[ "Programming Language :: Python :: 3", ], diff --git a/rocm_smi/example/rocm_smi_example.cc b/rocm_smi/example/rocm_smi_example.cc index 8efa6e9288..d5ab8b1cf5 100644 --- a/rocm_smi/example/rocm_smi_example.cc +++ b/rocm_smi/example/rocm_smi_example.cc @@ -695,7 +695,7 @@ static rsmi_status_t test_set_memory_partition(uint32_t dv_ind) { } template constexpr float convert_mw_to_w(T mw) { - return static_cast(mw / 1000.0); + return static_cast(static_cast(mw) / 1000.0); } @@ -1112,7 +1112,7 @@ int main() { if (ret == RSMI_STATUS_SUCCESS) { ret = rsmi_dev_fan_speed_max_get(i, 0, &val_ui64); CHK_AND_PRINT_RSMI_ERR_RET(ret) - std::cout << (static_cast(val_i64)/val_ui64) * 100; + std::cout << (static_cast(val_i64)/static_cast(val_ui64)) * 100; std::cout << "% (" << std::dec << val_i64 << "/" << std::dec << val_ui64 << ")" << "\n"; } diff --git a/rocm_smi/include/rocm_smi/kfd_ioctl.h b/rocm_smi/include/rocm_smi/kfd_ioctl.h index 99895d2036..2334afb9c0 100644 --- a/rocm_smi/include/rocm_smi/kfd_ioctl.h +++ b/rocm_smi/include/rocm_smi/kfd_ioctl.h @@ -20,28 +20,37 @@ * THE SOFTWARE. */ -#ifndef INCLUDE_ROCM_SMI_KFD_IOCTL_H_ -#define INCLUDE_ROCM_SMI_KFD_IOCTL_H_ +#ifndef KFD_IOCTL_H_INCLUDED +#define KFD_IOCTL_H_INCLUDED -#include +#include #include +/* + * - 1.1 - initial version + * - 1.3 - Add SMI events support + * - 1.4 - Indicate new SRAM EDC bit in device properties + * - 1.5 - Add SVM API + * - 1.6 - Query clear flags in SVM get_attr API + * - 1.7 - Checkpoint Restore (CRIU) API + * - 1.8 - CRIU - Support for SDMA transfers with GTT BOs + * - 1.9 - Add available memory ioctl + * - 1.10 - Add SMI profiler event log + * - 1.11 - Add unified memory for ctx save/restore area + * - 1.12 - Add DMA buf export ioctl + * - 1.13 - Add debugger API + * - 1.14 - Update kfd_event_data + * - 1.15 - Enable managing mappings in compute VMs with GEM_VA ioctl + * - 1.16 - Add contiguous VRAM allocation flag + */ #define KFD_IOCTL_MAJOR_VERSION 1 -#define KFD_IOCTL_MINOR_VERSION 2 -#define KFD_IOCTL_DBG_MAJOR_VERSION 1 -#define KFD_IOCTL_DBG_MINOR_VERSION 0 +#define KFD_IOCTL_MINOR_VERSION 16 struct kfd_ioctl_get_version_args { __u32 major_version; /* from KFD */ __u32 minor_version; /* from KFD */ }; -struct kfd_ioctl_get_available_memory_args { - __u64 available; /* from KFD */ - __u32 gpu_id; /* to KFD */ - __u32 pad; -}; - /* For kfd_ioctl_create_queue_args.queue_type. */ #define KFD_IOC_QUEUE_TYPE_COMPUTE 0x0 #define KFD_IOC_QUEUE_TYPE_SDMA 0x1 @@ -99,17 +108,36 @@ struct kfd_ioctl_get_queue_wave_state_args { __u32 pad; }; -struct kfd_queue_snapshot_entry { - __u64 ring_base_address; - __u64 write_pointer_address; - __u64 read_pointer_address; - __u64 ctx_save_restore_address; - __u32 queue_id; +struct kfd_ioctl_get_available_memory_args { + __u64 available; /* from KFD */ + __u32 gpu_id; /* to KFD */ + __u32 pad; +}; + +struct kfd_dbg_device_info_entry { + __u64 exception_status; + __u64 lds_base; + __u64 lds_limit; + __u64 scratch_base; + __u64 scratch_limit; + __u64 gpuvm_base; + __u64 gpuvm_limit; __u32 gpu_id; - __u32 ring_size; - __u32 queue_type; - __u32 queue_status; - __u32 reserved[19]; + __u32 location_id; + __u32 vendor_id; + __u32 device_id; + __u32 revision_id; + __u32 subsystem_vendor_id; + __u32 subsystem_device_id; + __u32 fw_version; + __u32 gfx_target_version; + __u32 simd_count; + __u32 max_waves_per_simd; + __u32 array_count; + __u32 simd_arrays_per_engine; + __u32 num_xcc; + __u32 capability; + __u32 debug_prop; }; /* For kfd_ioctl_set_memory_policy_args.default_policy and alternate_policy */ @@ -208,88 +236,17 @@ struct kfd_ioctl_dbg_wave_control_args { __u32 buf_size_in_bytes; /*including gpu_id and buf_size */ }; -/* mapping event types to API spec */ -#define KFD_DBG_EV_STATUS_TRAP 1 -#define KFD_DBG_EV_STATUS_VMFAULT 2 -#define KFD_DBG_EV_STATUS_SUSPENDED 4 -#define KFD_DBG_EV_STATUS_NEW_QUEUE 8 -#define KFD_DBG_EV_FLAG_CLEAR_STATUS 1 +#define KFD_INVALID_FD 0xffffffff -#define KFD_INVALID_QUEUEID 0xffffffff - -/* KFD_IOC_DBG_TRAP_ENABLE: - * ptr: unused - * data1: 0=disable, 1=enable - * data2: queue ID (for future use) - * data3: return value for fd - */ -#define KFD_IOC_DBG_TRAP_ENABLE 0 - -/* KFD_IOC_DBG_TRAP_SET_WAVE_LAUNCH_OVERRIDE: - * ptr: unused - * data1: override mode: 0=OR, 1=REPLACE - * data2: mask - * data3: unused - */ -#define KFD_IOC_DBG_TRAP_SET_WAVE_LAUNCH_OVERRIDE 1 - -/* KFD_IOC_DBG_TRAP_SET_WAVE_LAUNCH_MODE: - * ptr: unused - * data1: 0=normal, 1=halt, 2=kill, 3=singlestep, 4=disable - * data2: unused - * data3: unused - */ -#define KFD_IOC_DBG_TRAP_SET_WAVE_LAUNCH_MODE 2 - -/* KFD_IOC_DBG_TRAP_NODE_SUSPEND: - * ptr: pointer to an array of Queues IDs - * data1: flags - * data2: number of queues - * data3: grace period - */ -#define KFD_IOC_DBG_TRAP_NODE_SUSPEND 3 - -/* KFD_IOC_DBG_TRAP_NODE_RESUME: - * ptr: pointer to an array of Queues IDs - * data1: flags - * data2: number of queues - * data3: unused - */ -#define KFD_IOC_DBG_TRAP_NODE_RESUME 4 - -/* KFD_IOC_DBG_TRAP_QUERY_DEBUG_EVENT: - * ptr: unused - * data1: queue id (IN/OUT) - * data2: flags (IN) - * data3: suspend[2:2], event type [1:0] (OUT) - */ -#define KFD_IOC_DBG_TRAP_QUERY_DEBUG_EVENT 5 - -/* KFD_IOC_DBG_TRAP_GET_QUEUE_SNAPSHOT: - * ptr: user buffer (IN) - * data1: flags (IN) - * data2: number of queue snapshot entries (IN/OUT) - * data3: unused - */ -#define KFD_IOC_DBG_TRAP_GET_QUEUE_SNAPSHOT 6 - -/* KFD_IOC_DBG_TRAP_GET_VERSION: - * prt: unsused - * data1: major version (OUT) - * data2: minor version (OUT) - * data3: unused - */ -#define KFD_IOC_DBG_TRAP_GET_VERSION 7 - - -struct kfd_ioctl_dbg_trap_args { +struct kfd_ioctl_dbg_trap_args_deprecated { + __u64 exception_mask; /* to KFD */ __u64 ptr; /* to KFD -- used for pointer arguments: queue arrays */ __u32 pid; /* to KFD */ - __u32 gpu_id; /* to KFD */ __u32 op; /* to KFD */ __u32 data1; /* to KFD */ __u32 data2; /* to KFD */ __u32 data3; /* to KFD */ + __u32 data4; /* to KFD */ }; /* Matching HSA_EVENTTYPE */ @@ -328,7 +285,8 @@ struct kfd_ioctl_create_event_args { __u32 event_trigger_data; /* from KFD - signal events only */ __u32 event_type; /* to KFD */ __u32 auto_reset; /* to KFD */ - __u32 node_id; /* to KFD - only valid for certain event types */ + __u32 node_id; /* to KFD - only valid for certain + event types */ __u32 event_id; /* from KFD */ __u32 event_slot_index; /* from KFD */ }; @@ -360,11 +318,12 @@ struct kfd_hsa_memory_exception_data { struct kfd_memory_exception_failure failure; __u64 va; __u32 gpu_id; - __u32 ErrorType; // 0 = no RAS error, - // 1 = ECC_SRAM, - // 2 = Link_SYNFLOOD (poison), - // 3 = GPU hang (not attributable to a specific cause), - // other values reserved + __u32 ErrorType; /* 0 = no RAS error, + * 1 = ECC_SRAM, + * 2 = Link_SYNFLOOD (poison), + * 3 = GPU hang (not attributable to a specific cause), + * other values reserved + */ }; /* hw exception data */ @@ -375,21 +334,29 @@ struct kfd_hsa_hw_exception_data { __u32 gpu_id; }; +/* hsa signal event data */ +struct kfd_hsa_signal_event_data { + __u64 last_event_age; /* to and from KFD */ +}; + /* Event data */ struct kfd_event_data { union { + /* From KFD */ struct kfd_hsa_memory_exception_data memory_exception_data; struct kfd_hsa_hw_exception_data hw_exception_data; - }; /* From KFD */ - __u64 kfd_event_data_ext; // pointer to an extension structure - // for future exception types + /* To and From KFD */ + struct kfd_hsa_signal_event_data signal_event_data; + }; + __u64 kfd_event_data_ext; /* pointer to an extension structure + for future exception types */ __u32 event_id; /* to KFD */ __u32 pad; }; struct kfd_ioctl_wait_events_args { - __u64 events_ptr; // pointed to struct - // kfd_event_data array, to KFD + __u64 events_ptr; /* pointed to struct + kfd_event_data array, to KFD */ __u32 num_events; /* to KFD */ __u32 wait_for_all; /* to KFD */ __u32 timeout; /* to KFD */ @@ -450,6 +417,9 @@ struct kfd_ioctl_acquire_vm_args { #define KFD_IOC_ALLOC_MEM_FLAGS_NO_SUBSTITUTE (1 << 28) #define KFD_IOC_ALLOC_MEM_FLAGS_AQL_QUEUE_MEM (1 << 27) #define KFD_IOC_ALLOC_MEM_FLAGS_COHERENT (1 << 26) +#define KFD_IOC_ALLOC_MEM_FLAGS_UNCACHED (1 << 25) +#define KFD_IOC_ALLOC_MEM_FLAGS_EXT_COHERENT (1 << 24) +#define KFD_IOC_ALLOC_MEM_FLAGS_CONTIGUOUS (1 << 23) /* Allocate memory for later SVM (shared virtual memory) mapping. * @@ -524,14 +494,15 @@ struct kfd_ioctl_alloc_queue_gws_args { __u32 queue_id; /* to KFD */ __u32 num_gws; /* to KFD */ __u32 first_gws; /* from KFD */ - __u32 pad; /* to KFD */ + __u32 pad; }; struct kfd_ioctl_get_dmabuf_info_args { __u64 size; /* from KFD */ __u64 metadata_ptr; /* to KFD */ - __u32 metadata_size; // to KFD (space allocated by user) - // from KFD (actual metadata size) + __u32 metadata_size; /* to KFD (space allocated by user) + * from KFD (actual metadata size) + */ __u32 gpu_id; /* from KFD */ __u32 flags; /* from KFD (KFD_IOC_ALLOC_MEM_FLAGS) */ __u32 dmabuf_fd; /* to KFD */ @@ -544,6 +515,12 @@ struct kfd_ioctl_import_dmabuf_args { __u32 dmabuf_fd; /* to KFD */ }; +struct kfd_ioctl_export_dmabuf_args { + __u64 handle; /* to KFD */ + __u32 flags; /* to KFD */ + __u32 dmabuf_fd; /* from KFD */ +}; + /* * KFD SMI(System Management Interface) events */ @@ -553,16 +530,203 @@ enum kfd_smi_event { KFD_SMI_EVENT_THERMAL_THROTTLE = 2, KFD_SMI_EVENT_GPU_PRE_RESET = 3, KFD_SMI_EVENT_GPU_POST_RESET = 4, - KFD_SMI_EVENT_RING_HANG = 5, + KFD_SMI_EVENT_MIGRATE_START = 5, + KFD_SMI_EVENT_MIGRATE_END = 6, + KFD_SMI_EVENT_PAGE_FAULT_START = 7, + KFD_SMI_EVENT_PAGE_FAULT_END = 8, + KFD_SMI_EVENT_QUEUE_EVICTION = 9, + KFD_SMI_EVENT_QUEUE_RESTORE = 10, + KFD_SMI_EVENT_UNMAP_FROM_GPU = 11, + + /* + * max event number, as a flag bit to get events from all processes, + * this requires super user permission, otherwise will not be able to + * receive event from any process. Without this flag to receive events + * from same process. + */ + KFD_SMI_EVENT_ALL_PROCESS = 64 +}; + +enum KFD_MIGRATE_TRIGGERS { + KFD_MIGRATE_TRIGGER_PREFETCH, + KFD_MIGRATE_TRIGGER_PAGEFAULT_GPU, + KFD_MIGRATE_TRIGGER_PAGEFAULT_CPU, + KFD_MIGRATE_TRIGGER_TTM_EVICTION +}; + +enum KFD_QUEUE_EVICTION_TRIGGERS { + KFD_QUEUE_EVICTION_TRIGGER_SVM, + KFD_QUEUE_EVICTION_TRIGGER_USERPTR, + KFD_QUEUE_EVICTION_TRIGGER_TTM, + KFD_QUEUE_EVICTION_TRIGGER_SUSPEND, + KFD_QUEUE_EVICTION_CRIU_CHECKPOINT, + KFD_QUEUE_EVICTION_CRIU_RESTORE +}; + +enum KFD_SVM_UNMAP_TRIGGERS { + KFD_SVM_UNMAP_TRIGGER_MMU_NOTIFY, + KFD_SVM_UNMAP_TRIGGER_MMU_NOTIFY_MIGRATE, + KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU }; #define KFD_SMI_EVENT_MASK_FROM_INDEX(i) (1ULL << ((i) - 1)) +#define KFD_SMI_EVENT_MSG_SIZE 96 struct kfd_ioctl_smi_events_args { - __u32 gpuid; /* to KFD */ + __u32 gpuid; /* to KFD */ __u32 anon_fd; /* from KFD */ }; +/** + * kfd_ioctl_spm_op - SPM ioctl operations + * + * @KFD_IOCTL_SPM_OP_ACQUIRE: acquire exclusive access to SPM + * @KFD_IOCTL_SPM_OP_RELEASE: release exclusive access to SPM + * @KFD_IOCTL_SPM_OP_SET_DEST_BUF: set or unset destination buffer for SPM streaming + */ +enum kfd_ioctl_spm_op { + KFD_IOCTL_SPM_OP_ACQUIRE, + KFD_IOCTL_SPM_OP_RELEASE, + KFD_IOCTL_SPM_OP_SET_DEST_BUF +}; + +/** + * kfd_ioctl_spm_args - Arguments for SPM ioctl + * + * @op[in]: specifies the operation to perform + * @gpu_id[in]: GPU ID of the GPU to profile + * @dst_buf[in]: used for the address of the destination buffer + * in @KFD_IOCTL_SPM_SET_DEST_BUFFER + * @buf_size[in]: size of the destination buffer + * @timeout[in/out]: [in]: timeout in milliseconds, [out]: amount of time left + * `in the timeout window + * @bytes_copied[out]: amount of data that was copied to the previous dest_buf + * @has_data_loss: boolean indicating whether data was lost + * (e.g. due to a ring-buffer overflow) + * + * This ioctl performs different functions depending on the @op parameter. + * + * KFD_IOCTL_SPM_OP_ACQUIRE + * ------------------------ + * + * Acquires exclusive access of SPM on the specified @gpu_id for the calling process. + * This must be called before using KFD_IOCTL_SPM_OP_SET_DEST_BUF. + * + * KFD_IOCTL_SPM_OP_RELEASE + * ------------------------ + * + * Releases exclusive access of SPM on the specified @gpu_id for the calling process, + * which allows another process to acquire it in the future. + * + * KFD_IOCTL_SPM_OP_SET_DEST_BUF + * ----------------------------- + * + * If @dst_buf is NULL, the destination buffer address is unset and copying of counters + * is stopped. + * + * If @dst_buf is not NULL, it specifies the pointer to a new destination buffer. + * @buf_size specifies the size of the buffer. + * + * If @timeout is non-0, the call will wait for up to @timeout ms for the previous + * buffer to be filled. If previous buffer to be filled before timeout, the @timeout + * will be updated value with the time remaining. If the timeout is exceeded, the function + * copies any partial data available into the previous user buffer and returns success. + * The amount of valid data in the previous user buffer is indicated by @bytes_copied. + * + * If @timeout is 0, the function immediately replaces the previous destination buffer + * without waiting for the previous buffer to be filled. That means the previous buffer + * may only be partially filled, and @bytes_copied will indicate how much data has been + * copied to it. + * + * If data was lost, e.g. due to a ring buffer overflow, @has_data_loss will be non-0. + * + * Returns negative error code on failure, 0 on success. + */ +struct kfd_ioctl_spm_args { + __u64 dest_buf; + __u32 buf_size; + __u32 op; + __u32 timeout; + __u32 gpu_id; + __u32 bytes_copied; + __u32 has_data_loss; +}; + +/************************************************************************************************** + * CRIU IOCTLs (Checkpoint Restore In Userspace) + * + * When checkpointing a process, the userspace application will perform: + * 1. PROCESS_INFO op to determine current process information. This pauses execution and evicts + * all the queues. + * 2. CHECKPOINT op to checkpoint process contents (BOs, queues, events, svm-ranges) + * 3. UNPAUSE op to un-evict all the queues + * + * When restoring a process, the CRIU userspace application will perform: + * + * 1. RESTORE op to restore process contents + * 2. RESUME op to start the process + * + * Note: Queues are forced into an evicted state after a successful PROCESS_INFO. User + * application needs to perform an UNPAUSE operation after calling PROCESS_INFO. + */ + +enum kfd_criu_op { + KFD_CRIU_OP_PROCESS_INFO, + KFD_CRIU_OP_CHECKPOINT, + KFD_CRIU_OP_UNPAUSE, + KFD_CRIU_OP_RESTORE, + KFD_CRIU_OP_RESUME, +}; + +/** + * kfd_ioctl_criu_args - Arguments perform CRIU operation + * @devices: [in/out] User pointer to memory location for devices information. + * This is an array of type kfd_criu_device_bucket. + * @bos: [in/out] User pointer to memory location for BOs information + * This is an array of type kfd_criu_bo_bucket. + * @priv_data: [in/out] User pointer to memory location for private data + * @priv_data_size: [in/out] Size of priv_data in bytes + * @num_devices: [in/out] Number of GPUs used by process. Size of @devices array. + * @num_bos [in/out] Number of BOs used by process. Size of @bos array. + * @num_objects: [in/out] Number of objects used by process. Objects are opaque to + * user application. + * @pid: [in/out] PID of the process being checkpointed + * @op [in] Type of operation (kfd_criu_op) + * + * Return: 0 on success, -errno on failure + */ +struct kfd_ioctl_criu_args { + __u64 devices; /* Used during ops: CHECKPOINT, RESTORE */ + __u64 bos; /* Used during ops: CHECKPOINT, RESTORE */ + __u64 priv_data; /* Used during ops: CHECKPOINT, RESTORE */ + __u64 priv_data_size; /* Used during ops: PROCESS_INFO, RESTORE */ + __u32 num_devices; /* Used during ops: PROCESS_INFO, RESTORE */ + __u32 num_bos; /* Used during ops: PROCESS_INFO, RESTORE */ + __u32 num_objects; /* Used during ops: PROCESS_INFO, RESTORE */ + __u32 pid; /* Used during ops: PROCESS_INFO, RESUME */ + __u32 op; +}; + +struct kfd_criu_device_bucket { + __u32 user_gpu_id; + __u32 actual_gpu_id; + __u32 drm_fd; + __u32 pad; +}; + +struct kfd_criu_bo_bucket { + __u64 addr; + __u64 size; + __u64 offset; + __u64 restored_offset; /* During restore, updated offset for BO */ + __u32 gpu_id; /* This is the user_gpu_id */ + __u32 alloc_flags; + __u32 dmabuf_fd; + __u32 pad; +}; + +/* CRIU IOCTLs - END */ +/**************************************************************************************************/ /* Register offset inside the remapped mmio page */ enum kfd_mmio_remap { @@ -574,33 +738,19 @@ struct kfd_ioctl_ipc_export_handle_args { __u64 handle; /* to KFD */ __u32 share_handle[4]; /* from KFD */ __u32 gpu_id; /* to KFD */ - __u32 pad; + __u32 flags; /* to KFD */ }; struct kfd_ioctl_ipc_import_handle_args { __u64 handle; /* from KFD */ __u64 va_addr; /* to KFD */ - __u64 mmap_offset; /* from KFD */ + __u64 mmap_offset; /* from KFD */ __u32 share_handle[4]; /* to KFD */ __u32 gpu_id; /* to KFD */ - __u32 pad; + __u32 flags; /* from KFD */ }; -struct kfd_memory_range { - __u64 va_addr; - __u64 size; -}; - -/* flags definitions - * BIT0: 0: read operation, 1: write operation. - * This also identifies if the src or dst array belongs to remote process - */ -#define KFD_CROSS_MEMORY_RW_BIT (1 << 0) -#define KFD_SET_CROSS_MEMORY_READ(flags) (flags &= ~KFD_CROSS_MEMORY_RW_BIT) -#define KFD_SET_CROSS_MEMORY_WRITE(flags) (flags |= KFD_CROSS_MEMORY_RW_BIT) -#define KFD_IS_CROSS_MEMORY_WRITE(flags) (flags & KFD_CROSS_MEMORY_RW_BIT) // NOLINT - -struct kfd_ioctl_cross_memory_copy_args { +struct kfd_ioctl_cross_memory_copy_deprecated_args { /* to KFD: Process ID of the remote process */ __u32 pid; /* to KFD: See above definition */ @@ -617,6 +767,874 @@ struct kfd_ioctl_cross_memory_copy_args { __u64 bytes_copied; }; +/* Guarantee host access to memory */ +#define KFD_IOCTL_SVM_FLAG_HOST_ACCESS 0x00000001 +/* Fine grained coherency between all devices with access */ +#define KFD_IOCTL_SVM_FLAG_COHERENT 0x00000002 +/* Use any GPU in same hive as preferred device */ +#define KFD_IOCTL_SVM_FLAG_HIVE_LOCAL 0x00000004 +/* GPUs only read, allows replication */ +#define KFD_IOCTL_SVM_FLAG_GPU_RO 0x00000008 +/* Allow execution on GPU */ +#define KFD_IOCTL_SVM_FLAG_GPU_EXEC 0x00000010 +/* GPUs mostly read, may allow similar optimizations as RO, but writes fault */ +#define KFD_IOCTL_SVM_FLAG_GPU_READ_MOSTLY 0x00000020 +/* Keep GPU memory mapping always valid as if XNACK is disable */ +#define KFD_IOCTL_SVM_FLAG_GPU_ALWAYS_MAPPED 0x00000040 +/* Fine grained coherency between all devices using device-scope atomics */ +#define KFD_IOCTL_SVM_FLAG_EXT_COHERENT 0x00000080 + +/** + * kfd_ioctl_svm_op - SVM ioctl operations + * + * @KFD_IOCTL_SVM_OP_SET_ATTR: Modify one or more attributes + * @KFD_IOCTL_SVM_OP_GET_ATTR: Query one or more attributes + */ +enum kfd_ioctl_svm_op { + KFD_IOCTL_SVM_OP_SET_ATTR, + KFD_IOCTL_SVM_OP_GET_ATTR +}; + +/** kfd_ioctl_svm_location - Enum for preferred and prefetch locations + * + * GPU IDs are used to specify GPUs as preferred and prefetch locations. + * Below definitions are used for system memory or for leaving the preferred + * location unspecified. + */ +enum kfd_ioctl_svm_location { + KFD_IOCTL_SVM_LOCATION_SYSMEM = 0, + KFD_IOCTL_SVM_LOCATION_UNDEFINED = 0xffffffff +}; + +/** + * kfd_ioctl_svm_attr_type - SVM attribute types + * + * @KFD_IOCTL_SVM_ATTR_PREFERRED_LOC: gpuid of the preferred location, 0 for + * system memory + * @KFD_IOCTL_SVM_ATTR_PREFETCH_LOC: gpuid of the prefetch location, 0 for + * system memory. Setting this triggers an + * immediate prefetch (migration). + * @KFD_IOCTL_SVM_ATTR_ACCESS: + * @KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE: + * @KFD_IOCTL_SVM_ATTR_NO_ACCESS: specify memory access for the gpuid given + * by the attribute value + * @KFD_IOCTL_SVM_ATTR_SET_FLAGS: bitmask of flags to set (see + * KFD_IOCTL_SVM_FLAG_...) + * @KFD_IOCTL_SVM_ATTR_CLR_FLAGS: bitmask of flags to clear + * @KFD_IOCTL_SVM_ATTR_GRANULARITY: migration granularity + * (log2 num pages) + */ +enum kfd_ioctl_svm_attr_type { + KFD_IOCTL_SVM_ATTR_PREFERRED_LOC, + KFD_IOCTL_SVM_ATTR_PREFETCH_LOC, + KFD_IOCTL_SVM_ATTR_ACCESS, + KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE, + KFD_IOCTL_SVM_ATTR_NO_ACCESS, + KFD_IOCTL_SVM_ATTR_SET_FLAGS, + KFD_IOCTL_SVM_ATTR_CLR_FLAGS, + KFD_IOCTL_SVM_ATTR_GRANULARITY +}; + +/** + * kfd_ioctl_svm_attribute - Attributes as pairs of type and value + * + * The meaning of the @value depends on the attribute type. + * + * @type: attribute type (see enum @kfd_ioctl_svm_attr_type) + * @value: attribute value + */ +struct kfd_ioctl_svm_attribute { + __u32 type; + __u32 value; +}; + +/** + * kfd_ioctl_svm_args - Arguments for SVM ioctl + * + * @op specifies the operation to perform (see enum + * @kfd_ioctl_svm_op). @start_addr and @size are common for all + * operations. + * + * A variable number of attributes can be given in @attrs. + * @nattr specifies the number of attributes. New attributes can be + * added in the future without breaking the ABI. If unknown attributes + * are given, the function returns -EINVAL. + * + * @KFD_IOCTL_SVM_OP_SET_ATTR sets attributes for a virtual address + * range. It may overlap existing virtual address ranges. If it does, + * the existing ranges will be split such that the attribute changes + * only apply to the specified address range. + * + * @KFD_IOCTL_SVM_OP_GET_ATTR returns the intersection of attributes + * over all memory in the given range and returns the result as the + * attribute value. If different pages have different preferred or + * prefetch locations, 0xffffffff will be returned for + * @KFD_IOCTL_SVM_ATTR_PREFERRED_LOC or + * @KFD_IOCTL_SVM_ATTR_PREFETCH_LOC resepctively. For + * @KFD_IOCTL_SVM_ATTR_SET_FLAGS, flags of all pages will be + * aggregated by bitwise AND. That means, a flag will be set in the + * output, if that flag is set for all pages in the range. For + * @KFD_IOCTL_SVM_ATTR_CLR_FLAGS, flags of all pages will be + * aggregated by bitwise NOR. That means, a flag will be set in the + * output, if that flag is clear for all pages in the range. + * The minimum migration granularity throughout the range will be + * returned for @KFD_IOCTL_SVM_ATTR_GRANULARITY. + * + * Querying of accessibility attributes works by initializing the + * attribute type to @KFD_IOCTL_SVM_ATTR_ACCESS and the value to the + * GPUID being queried. Multiple attributes can be given to allow + * querying multiple GPUIDs. The ioctl function overwrites the + * attribute type to indicate the access for the specified GPU. + */ +struct kfd_ioctl_svm_args { + __u64 start_addr; + __u64 size; + __u32 op; + __u32 nattr; + /* Variable length array of attributes */ + struct kfd_ioctl_svm_attribute attrs[]; +}; + +/** + * kfd_ioctl_set_xnack_mode_args - Arguments for set_xnack_mode + * + * @xnack_enabled: [in/out] Whether to enable XNACK mode for this process + * + * @xnack_enabled indicates whether recoverable page faults should be + * enabled for the current process. 0 means disabled, positive means + * enabled, negative means leave unchanged. If enabled, virtual address + * translations on GFXv9 and later AMD GPUs can return XNACK and retry + * the access until a valid PTE is available. This is used to implement + * device page faults. + * + * On output, @xnack_enabled returns the (new) current mode (0 or + * positive). Therefore, a negative input value can be used to query + * the current mode without changing it. + * + * The XNACK mode fundamentally changes the way SVM managed memory works + * in the driver, with subtle effects on application performance and + * functionality. + * + * Enabling XNACK mode requires shader programs to be compiled + * differently. Furthermore, not all GPUs support changing the mode + * per-process. Therefore changing the mode is only allowed while no + * user mode queues exist in the process. This ensure that no shader + * code is running that may be compiled for the wrong mode. And GPUs + * that cannot change to the requested mode will prevent the XNACK + * mode from occurring. All GPUs used by the process must be in the + * same XNACK mode. + * + * GFXv8 or older GPUs do not support 48 bit virtual addresses or SVM. + * Therefore those GPUs are not considered for the XNACK mode switch. + * + * Return: 0 on success, -errno on failure + */ +struct kfd_ioctl_set_xnack_mode_args { + __s32 xnack_enabled; +}; + +/* Wave launch override modes */ +enum kfd_dbg_trap_override_mode { + KFD_DBG_TRAP_OVERRIDE_OR = 0, + KFD_DBG_TRAP_OVERRIDE_REPLACE = 1 +}; + +/* Wave launch overrides */ +enum kfd_dbg_trap_mask { + KFD_DBG_TRAP_MASK_FP_INVALID = 1, + KFD_DBG_TRAP_MASK_FP_INPUT_DENORMAL = 2, + KFD_DBG_TRAP_MASK_FP_DIVIDE_BY_ZERO = 4, + KFD_DBG_TRAP_MASK_FP_OVERFLOW = 8, + KFD_DBG_TRAP_MASK_FP_UNDERFLOW = 16, + KFD_DBG_TRAP_MASK_FP_INEXACT = 32, + KFD_DBG_TRAP_MASK_INT_DIVIDE_BY_ZERO = 64, + KFD_DBG_TRAP_MASK_DBG_ADDRESS_WATCH = 128, + KFD_DBG_TRAP_MASK_DBG_MEMORY_VIOLATION = 256, + KFD_DBG_TRAP_MASK_TRAP_ON_WAVE_START = (1 << 30), + KFD_DBG_TRAP_MASK_TRAP_ON_WAVE_END = (1 << 31) +}; + +/* Wave launch modes */ +enum kfd_dbg_trap_wave_launch_mode { + KFD_DBG_TRAP_WAVE_LAUNCH_MODE_NORMAL = 0, + KFD_DBG_TRAP_WAVE_LAUNCH_MODE_HALT = 1, + KFD_DBG_TRAP_WAVE_LAUNCH_MODE_DEBUG = 3 +}; + +/* Address watch modes */ +enum kfd_dbg_trap_address_watch_mode { + KFD_DBG_TRAP_ADDRESS_WATCH_MODE_READ = 0, + KFD_DBG_TRAP_ADDRESS_WATCH_MODE_NONREAD = 1, + KFD_DBG_TRAP_ADDRESS_WATCH_MODE_ATOMIC = 2, + KFD_DBG_TRAP_ADDRESS_WATCH_MODE_ALL = 3 +}; + +/* Additional wave settings */ +enum kfd_dbg_trap_flags { + KFD_DBG_TRAP_FLAG_SINGLE_MEM_OP = 1, + KFD_DBG_TRAP_FLAG_SINGLE_ALU_OP = 2, +}; + +/* Trap exceptions */ +enum kfd_dbg_trap_exception_code { + EC_NONE = 0, + /* per queue */ + EC_QUEUE_WAVE_ABORT = 1, + EC_QUEUE_WAVE_TRAP = 2, + EC_QUEUE_WAVE_MATH_ERROR = 3, + EC_QUEUE_WAVE_ILLEGAL_INSTRUCTION = 4, + EC_QUEUE_WAVE_MEMORY_VIOLATION = 5, + EC_QUEUE_WAVE_APERTURE_VIOLATION = 6, + EC_QUEUE_PACKET_DISPATCH_DIM_INVALID = 16, + EC_QUEUE_PACKET_DISPATCH_GROUP_SEGMENT_SIZE_INVALID = 17, + EC_QUEUE_PACKET_DISPATCH_CODE_INVALID = 18, + EC_QUEUE_PACKET_RESERVED = 19, + EC_QUEUE_PACKET_UNSUPPORTED = 20, + EC_QUEUE_PACKET_DISPATCH_WORK_GROUP_SIZE_INVALID = 21, + EC_QUEUE_PACKET_DISPATCH_REGISTER_INVALID = 22, + EC_QUEUE_PACKET_VENDOR_UNSUPPORTED = 23, + EC_QUEUE_PREEMPTION_ERROR = 30, + EC_QUEUE_NEW = 31, + /* per device */ + EC_DEVICE_QUEUE_DELETE = 32, + EC_DEVICE_MEMORY_VIOLATION = 33, + EC_DEVICE_RAS_ERROR = 34, + EC_DEVICE_FATAL_HALT = 35, + EC_DEVICE_NEW = 36, + /* per process */ + EC_PROCESS_RUNTIME = 48, + EC_PROCESS_DEVICE_REMOVE = 49, + EC_MAX +}; + +/* Mask generated by ecode in kfd_dbg_trap_exception_code */ +#define KFD_EC_MASK(ecode) (1ULL << (ecode - 1)) + +/* Masks for exception code type checks below */ +#define KFD_EC_MASK_QUEUE (KFD_EC_MASK(EC_QUEUE_WAVE_ABORT) | \ + KFD_EC_MASK(EC_QUEUE_WAVE_TRAP) | \ + KFD_EC_MASK(EC_QUEUE_WAVE_MATH_ERROR) | \ + KFD_EC_MASK(EC_QUEUE_WAVE_ILLEGAL_INSTRUCTION) | \ + KFD_EC_MASK(EC_QUEUE_WAVE_MEMORY_VIOLATION) | \ + KFD_EC_MASK(EC_QUEUE_WAVE_APERTURE_VIOLATION) | \ + KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_DIM_INVALID) | \ + KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_GROUP_SEGMENT_SIZE_INVALID) | \ + KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_CODE_INVALID) | \ + KFD_EC_MASK(EC_QUEUE_PACKET_RESERVED) | \ + KFD_EC_MASK(EC_QUEUE_PACKET_UNSUPPORTED) | \ + KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_WORK_GROUP_SIZE_INVALID) | \ + KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_REGISTER_INVALID) | \ + KFD_EC_MASK(EC_QUEUE_PACKET_VENDOR_UNSUPPORTED) | \ + KFD_EC_MASK(EC_QUEUE_PREEMPTION_ERROR) | \ + KFD_EC_MASK(EC_QUEUE_NEW)) +#define KFD_EC_MASK_DEVICE (KFD_EC_MASK(EC_DEVICE_QUEUE_DELETE) | \ + KFD_EC_MASK(EC_DEVICE_RAS_ERROR) | \ + KFD_EC_MASK(EC_DEVICE_FATAL_HALT) | \ + KFD_EC_MASK(EC_DEVICE_MEMORY_VIOLATION) | \ + KFD_EC_MASK(EC_DEVICE_NEW)) +#define KFD_EC_MASK_PROCESS (KFD_EC_MASK(EC_PROCESS_RUNTIME) | \ + KFD_EC_MASK(EC_PROCESS_DEVICE_REMOVE)) +#define KFD_EC_MASK_PACKET (KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_DIM_INVALID) | \ + KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_GROUP_SEGMENT_SIZE_INVALID) | \ + KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_CODE_INVALID) | \ + KFD_EC_MASK(EC_QUEUE_PACKET_RESERVED) | \ + KFD_EC_MASK(EC_QUEUE_PACKET_UNSUPPORTED) | \ + KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_WORK_GROUP_SIZE_INVALID) | \ + KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_REGISTER_INVALID) | \ + KFD_EC_MASK(EC_QUEUE_PACKET_VENDOR_UNSUPPORTED)) + +/* Checks for exception code types for KFD search */ +#define KFD_DBG_EC_IS_VALID(ecode) (ecode > EC_NONE && ecode < EC_MAX) +#define KFD_DBG_EC_TYPE_IS_QUEUE(ecode) \ + (KFD_DBG_EC_IS_VALID(ecode) && !!(KFD_EC_MASK(ecode) & KFD_EC_MASK_QUEUE)) +#define KFD_DBG_EC_TYPE_IS_DEVICE(ecode) \ + (KFD_DBG_EC_IS_VALID(ecode) && !!(KFD_EC_MASK(ecode) & KFD_EC_MASK_DEVICE)) +#define KFD_DBG_EC_TYPE_IS_PROCESS(ecode) \ + (KFD_DBG_EC_IS_VALID(ecode) && !!(KFD_EC_MASK(ecode) & KFD_EC_MASK_PROCESS)) +#define KFD_DBG_EC_TYPE_IS_PACKET(ecode) \ + (KFD_DBG_EC_IS_VALID(ecode) && !!(KFD_EC_MASK(ecode) & KFD_EC_MASK_PACKET)) + + +/* Runtime enable states */ +enum kfd_dbg_runtime_state { + DEBUG_RUNTIME_STATE_DISABLED = 0, + DEBUG_RUNTIME_STATE_ENABLED = 1, + DEBUG_RUNTIME_STATE_ENABLED_BUSY = 2, + DEBUG_RUNTIME_STATE_ENABLED_ERROR = 3 +}; + +/* Runtime enable status */ +struct kfd_runtime_info { + __u64 r_debug; + __u32 runtime_state; + __u32 ttmp_setup; +}; + +/* Enable modes for runtime enable */ +#define KFD_RUNTIME_ENABLE_MODE_ENABLE_MASK 1 +#define KFD_RUNTIME_ENABLE_MODE_TTMP_SAVE_MASK 2 + +/** + * kfd_ioctl_runtime_enable_args - Arguments for runtime enable + * + * Coordinates debug exception signalling and debug device enablement with runtime. + * + * @r_debug - pointer to user struct for sharing information between ROCr and the debuggger + * @mode_mask - mask to set mode + * KFD_RUNTIME_ENABLE_MODE_ENABLE_MASK - enable runtime for debugging, otherwise disable + * KFD_RUNTIME_ENABLE_MODE_TTMP_SAVE_MASK - enable trap temporary setup (ignore on disable) + * @capabilities_mask - mask to notify runtime on what KFD supports + * + * Return - 0 on SUCCESS. + * - EBUSY if runtime enable call already pending. + * - EEXIST if user queues already active prior to call. + * If process is debug enabled, runtime enable will enable debug devices and + * wait for debugger process to send runtime exception EC_PROCESS_RUNTIME + * to unblock - see kfd_ioctl_dbg_trap_args. + * + */ +struct kfd_ioctl_runtime_enable_args { + __u64 r_debug; + __u32 mode_mask; + __u32 capabilities_mask; +}; + +/* Queue information */ +struct kfd_queue_snapshot_entry { + __u64 exception_status; + __u64 ring_base_address; + __u64 write_pointer_address; + __u64 read_pointer_address; + __u64 ctx_save_restore_address; + __u32 queue_id; + __u32 gpu_id; + __u32 ring_size; + __u32 queue_type; + __u32 ctx_save_restore_area_size; + __u32 reserved; +}; + +/* Queue status return for suspend/resume */ +#define KFD_DBG_QUEUE_ERROR_BIT 30 +#define KFD_DBG_QUEUE_INVALID_BIT 31 +#define KFD_DBG_QUEUE_ERROR_MASK (1 << KFD_DBG_QUEUE_ERROR_BIT) +#define KFD_DBG_QUEUE_INVALID_MASK (1 << KFD_DBG_QUEUE_INVALID_BIT) + +/* Context save area header information */ +struct kfd_context_save_area_header { + struct { + __u32 control_stack_offset; + __u32 control_stack_size; + __u32 wave_state_offset; + __u32 wave_state_size; + } wave_state; + __u32 debug_offset; + __u32 debug_size; + __u64 err_payload_addr; + __u32 err_event_id; + __u32 reserved1; +}; + +/* + * Debug operations + * + * For specifics on usage and return values, see documentation per operation + * below. Otherwise, generic error returns apply: + * - ESRCH if the process to debug does not exist. + * + * - EINVAL (with KFD_IOC_DBG_TRAP_ENABLE exempt) if operation + * KFD_IOC_DBG_TRAP_ENABLE has not succeeded prior. + * Also returns this error if GPU hardware scheduling is not supported. + * + * - EPERM (with KFD_IOC_DBG_TRAP_DISABLE exempt) if target process is not + * PTRACE_ATTACHED. KFD_IOC_DBG_TRAP_DISABLE is exempt to allow + * clean up of debug mode as long as process is debug enabled. + * + * - EACCES if any DBG_HW_OP (debug hardware operation) is requested when + * AMDKFD_IOC_RUNTIME_ENABLE has not succeeded prior. + * + * - ENODEV if any GPU does not support debugging on a DBG_HW_OP call. + * + * - Other errors may be returned when a DBG_HW_OP occurs while the GPU + * is in a fatal state. + * + */ +enum kfd_dbg_trap_operations { + KFD_IOC_DBG_TRAP_ENABLE = 0, + KFD_IOC_DBG_TRAP_DISABLE = 1, + KFD_IOC_DBG_TRAP_SEND_RUNTIME_EVENT = 2, + KFD_IOC_DBG_TRAP_SET_EXCEPTIONS_ENABLED = 3, + KFD_IOC_DBG_TRAP_SET_WAVE_LAUNCH_OVERRIDE = 4, /* DBG_HW_OP */ + KFD_IOC_DBG_TRAP_SET_WAVE_LAUNCH_MODE = 5, /* DBG_HW_OP */ + KFD_IOC_DBG_TRAP_SUSPEND_QUEUES = 6, /* DBG_HW_OP */ + KFD_IOC_DBG_TRAP_RESUME_QUEUES = 7, /* DBG_HW_OP */ + KFD_IOC_DBG_TRAP_SET_NODE_ADDRESS_WATCH = 8, /* DBG_HW_OP */ + KFD_IOC_DBG_TRAP_CLEAR_NODE_ADDRESS_WATCH = 9, /* DBG_HW_OP */ + KFD_IOC_DBG_TRAP_SET_FLAGS = 10, + KFD_IOC_DBG_TRAP_QUERY_DEBUG_EVENT = 11, + KFD_IOC_DBG_TRAP_QUERY_EXCEPTION_INFO = 12, + KFD_IOC_DBG_TRAP_GET_QUEUE_SNAPSHOT = 13, + KFD_IOC_DBG_TRAP_GET_DEVICE_SNAPSHOT = 14 +}; + +/** + * kfd_ioctl_dbg_trap_enable_args + * + * Arguments for KFD_IOC_DBG_TRAP_ENABLE. + * + * Enables debug session for target process. Call @op KFD_IOC_DBG_TRAP_DISABLE in + * kfd_ioctl_dbg_trap_args to disable debug session. + * + * @exception_mask (IN) - exceptions to raise to the debugger + * @rinfo_ptr (IN) - pointer to runtime info buffer (see kfd_runtime_info) + * @rinfo_size (IN/OUT) - size of runtime info buffer in bytes + * @dbg_fd (IN) - fd the KFD will nofify the debugger with of raised + * exceptions set in exception_mask. + * + * Generic errors apply (see kfd_dbg_trap_operations). + * Return - 0 on SUCCESS. + * Copies KFD saved kfd_runtime_info to @rinfo_ptr on enable. + * Size of kfd_runtime saved by the KFD returned to @rinfo_size. + * - EBADF if KFD cannot get a reference to dbg_fd. + * - EFAULT if KFD cannot copy runtime info to rinfo_ptr. + * - EINVAL if target process is already debug enabled. + * + */ +struct kfd_ioctl_dbg_trap_enable_args { + __u64 exception_mask; + __u64 rinfo_ptr; + __u32 rinfo_size; + __u32 dbg_fd; +}; + +/** + * kfd_ioctl_dbg_trap_send_runtime_event_args + * + * + * Arguments for KFD_IOC_DBG_TRAP_SEND_RUNTIME_EVENT. + * Raises exceptions to runtime. + * + * @exception_mask (IN) - exceptions to raise to runtime + * @gpu_id (IN) - target device id + * @queue_id (IN) - target queue id + * + * Generic errors apply (see kfd_dbg_trap_operations). + * Return - 0 on SUCCESS. + * - ENODEV if gpu_id not found. + * If exception_mask contains EC_PROCESS_RUNTIME, unblocks pending + * AMDKFD_IOC_RUNTIME_ENABLE call - see kfd_ioctl_runtime_enable_args. + * All other exceptions are raised to runtime through err_payload_addr. + * See kfd_context_save_area_header. + */ +struct kfd_ioctl_dbg_trap_send_runtime_event_args { + __u64 exception_mask; + __u32 gpu_id; + __u32 queue_id; +}; + +/** + * kfd_ioctl_dbg_trap_set_exceptions_enabled_args + * + * Arguments for KFD_IOC_SET_EXCEPTIONS_ENABLED + * Set new exceptions to be raised to the debugger. + * + * @exception_mask (IN) - new exceptions to raise the debugger + * + * Generic errors apply (see kfd_dbg_trap_operations). + * Return - 0 on SUCCESS. + */ +struct kfd_ioctl_dbg_trap_set_exceptions_enabled_args { + __u64 exception_mask; +}; + +/** + * kfd_ioctl_dbg_trap_set_wave_launch_override_args + * + * Arguments for KFD_IOC_DBG_TRAP_SET_WAVE_LAUNCH_OVERRIDE + * Enable HW exceptions to raise trap. + * + * @override_mode (IN) - see kfd_dbg_trap_override_mode + * @enable_mask (IN/OUT) - reference kfd_dbg_trap_mask. + * IN is the override modes requested to be enabled. + * OUT is referenced in Return below. + * @support_request_mask (IN/OUT) - reference kfd_dbg_trap_mask. + * IN is the override modes requested for support check. + * OUT is referenced in Return below. + * + * Generic errors apply (see kfd_dbg_trap_operations). + * Return - 0 on SUCCESS. + * Previous enablement is returned in @enable_mask. + * Actual override support is returned in @support_request_mask. + * - EINVAL if override mode is not supported. + * - EACCES if trap support requested is not actually supported. + * i.e. enable_mask (IN) is not a subset of support_request_mask (OUT). + * Otherwise it is considered a generic error (see kfd_dbg_trap_operations). + */ +struct kfd_ioctl_dbg_trap_set_wave_launch_override_args { + __u32 override_mode; + __u32 enable_mask; + __u32 support_request_mask; + __u32 pad; +}; + +/** + * kfd_ioctl_dbg_trap_set_wave_launch_mode_args + * + * Arguments for KFD_IOC_DBG_TRAP_SET_WAVE_LAUNCH_MODE + * Set wave launch mode. + * + * @mode (IN) - see kfd_dbg_trap_wave_launch_mode + * + * Generic errors apply (see kfd_dbg_trap_operations). + * Return - 0 on SUCCESS. + */ +struct kfd_ioctl_dbg_trap_set_wave_launch_mode_args { + __u32 launch_mode; + __u32 pad; +}; + +/** + * kfd_ioctl_dbg_trap_suspend_queues_ags + * + * Arguments for KFD_IOC_DBG_TRAP_SUSPEND_QUEUES + * Suspend queues. + * + * @exception_mask (IN) - raised exceptions to clear + * @queue_array_ptr (IN) - pointer to array of queue ids (u32 per queue id) + * to suspend + * @num_queues (IN) - number of queues to suspend in @queue_array_ptr + * @grace_period (IN) - wave time allowance before preemption + * per 1K GPU clock cycle unit + * + * Generic errors apply (see kfd_dbg_trap_operations). + * Destruction of a suspended queue is blocked until the queue is + * resumed. This allows the debugger to access queue information and + * the its context save area without running into a race condition on + * queue destruction. + * Automatically copies per queue context save area header information + * into the save area base + * (see kfd_queue_snapshot_entry and kfd_context_save_area_header). + * + * Return - Number of queues suspended on SUCCESS. + * . KFD_DBG_QUEUE_ERROR_MASK and KFD_DBG_QUEUE_INVALID_MASK masked + * for each queue id in @queue_array_ptr array reports unsuccessful + * suspend reason. + * KFD_DBG_QUEUE_ERROR_MASK = HW failure. + * KFD_DBG_QUEUE_INVALID_MASK = queue does not exist, is new or + * is being destroyed. + */ +struct kfd_ioctl_dbg_trap_suspend_queues_args { + __u64 exception_mask; + __u64 queue_array_ptr; + __u32 num_queues; + __u32 grace_period; +}; + +/** + * kfd_ioctl_dbg_trap_resume_queues_args + * + * Arguments for KFD_IOC_DBG_TRAP_RESUME_QUEUES + * Resume queues. + * + * @queue_array_ptr (IN) - pointer to array of queue ids (u32 per queue id) + * to resume + * @num_queues (IN) - number of queues to resume in @queue_array_ptr + * + * Generic errors apply (see kfd_dbg_trap_operations). + * Return - Number of queues resumed on SUCCESS. + * KFD_DBG_QUEUE_ERROR_MASK and KFD_DBG_QUEUE_INVALID_MASK mask + * for each queue id in @queue_array_ptr array reports unsuccessful + * resume reason. + * KFD_DBG_QUEUE_ERROR_MASK = HW failure. + * KFD_DBG_QUEUE_INVALID_MASK = queue does not exist. + */ +struct kfd_ioctl_dbg_trap_resume_queues_args { + __u64 queue_array_ptr; + __u32 num_queues; + __u32 pad; +}; + +/** + * kfd_ioctl_dbg_trap_set_node_address_watch_args + * + * Arguments for KFD_IOC_DBG_TRAP_SET_NODE_ADDRESS_WATCH + * Sets address watch for device. + * + * @address (IN) - watch address to set + * @mode (IN) - see kfd_dbg_trap_address_watch_mode + * @mask (IN) - watch address mask + * @gpu_id (IN) - target gpu to set watch point + * @id (OUT) - watch id allocated + * + * Generic errors apply (see kfd_dbg_trap_operations). + * Return - 0 on SUCCESS. + * Allocated watch ID returned to @id. + * - ENODEV if gpu_id not found. + * - ENOMEM if watch IDs can be allocated + */ +struct kfd_ioctl_dbg_trap_set_node_address_watch_args { + __u64 address; + __u32 mode; + __u32 mask; + __u32 gpu_id; + __u32 id; +}; + +/** + * kfd_ioctl_dbg_trap_clear_node_address_watch_args + * + * Arguments for KFD_IOC_DBG_TRAP_CLEAR_NODE_ADDRESS_WATCH + * Clear address watch for device. + * + * @gpu_id (IN) - target device to clear watch point + * @id (IN) - allocated watch id to clear + * + * Generic errors apply (see kfd_dbg_trap_operations). + * Return - 0 on SUCCESS. + * - ENODEV if gpu_id not found. + * - EINVAL if watch ID has not been allocated. + */ +struct kfd_ioctl_dbg_trap_clear_node_address_watch_args { + __u32 gpu_id; + __u32 id; +}; + +/** + * kfd_ioctl_dbg_trap_set_flags_args + * + * Arguments for KFD_IOC_DBG_TRAP_SET_FLAGS + * Sets flags for wave behaviour. + * + * @flags (IN/OUT) - IN = flags to enable, OUT = flags previously enabled + * + * Generic errors apply (see kfd_dbg_trap_operations). + * Return - 0 on SUCCESS. + * - EACCESS if any debug device does not allow flag options. + */ +struct kfd_ioctl_dbg_trap_set_flags_args { + __u32 flags; + __u32 pad; +}; + +/** + * kfd_ioctl_dbg_trap_query_debug_event_args + * + * Arguments for KFD_IOC_DBG_TRAP_QUERY_DEBUG_EVENT + * + * Find one or more raised exceptions. This function can return multiple + * exceptions from a single queue or a single device with one call. To find + * all raised exceptions, this function must be called repeatedly until it + * returns -EAGAIN. Returned exceptions can optionally be cleared by + * setting the corresponding bit in the @exception_mask input parameter. + * However, clearing an exception prevents retrieving further information + * about it with KFD_IOC_DBG_TRAP_QUERY_EXCEPTION_INFO. + * + * @exception_mask (IN/OUT) - exception to clear (IN) and raised (OUT) + * @gpu_id (OUT) - gpu id of exceptions raised + * @queue_id (OUT) - queue id of exceptions raised + * + * Generic errors apply (see kfd_dbg_trap_operations). + * Return - 0 on raised exception found + * Raised exceptions found are returned in @exception mask + * with reported source id returned in @gpu_id or @queue_id. + * - EAGAIN if no raised exception has been found + */ +struct kfd_ioctl_dbg_trap_query_debug_event_args { + __u64 exception_mask; + __u32 gpu_id; + __u32 queue_id; +}; + +/** + * kfd_ioctl_dbg_trap_query_exception_info_args + * + * Arguments KFD_IOC_DBG_TRAP_QUERY_EXCEPTION_INFO + * Get additional info on raised exception. + * + * @info_ptr (IN) - pointer to exception info buffer to copy to + * @info_size (IN/OUT) - exception info buffer size (bytes) + * @source_id (IN) - target gpu or queue id + * @exception_code (IN) - target exception + * @clear_exception (IN) - clear raised @exception_code exception + * (0 = false, 1 = true) + * + * Generic errors apply (see kfd_dbg_trap_operations). + * Return - 0 on SUCCESS. + * If @exception_code is EC_DEVICE_MEMORY_VIOLATION, copy @info_size(OUT) + * bytes of memory exception data to @info_ptr. + * If @exception_code is EC_PROCESS_RUNTIME, copy saved + * kfd_runtime_info to @info_ptr. + * Actual required @info_ptr size (bytes) is returned in @info_size. + */ +struct kfd_ioctl_dbg_trap_query_exception_info_args { + __u64 info_ptr; + __u32 info_size; + __u32 source_id; + __u32 exception_code; + __u32 clear_exception; +}; + +/** + * kfd_ioctl_dbg_trap_get_queue_snapshot_args + * + * Arguments KFD_IOC_DBG_TRAP_GET_QUEUE_SNAPSHOT + * Get queue information. + * + * @exception_mask (IN) - exceptions raised to clear + * @snapshot_buf_ptr (IN) - queue snapshot entry buffer (see kfd_queue_snapshot_entry) + * @num_queues (IN/OUT) - number of queue snapshot entries + * The debugger specifies the size of the array allocated in @num_queues. + * KFD returns the number of queues that actually existed. If this is + * larger than the size specified by the debugger, KFD will not overflow + * the array allocated by the debugger. + * + * @entry_size (IN/OUT) - size per entry in bytes + * The debugger specifies sizeof(struct kfd_queue_snapshot_entry) in + * @entry_size. KFD returns the number of bytes actually populated per + * entry. The debugger should use the KFD_IOCTL_MINOR_VERSION to determine, + * which fields in struct kfd_queue_snapshot_entry are valid. This allows + * growing the ABI in a backwards compatible manner. + * Note that entry_size(IN) should still be used to stride the snapshot buffer in the + * event that it's larger than actual kfd_queue_snapshot_entry. + * + * Generic errors apply (see kfd_dbg_trap_operations). + * Return - 0 on SUCCESS. + * Copies @num_queues(IN) queue snapshot entries of size @entry_size(IN) + * into @snapshot_buf_ptr if @num_queues(IN) > 0. + * Otherwise return @num_queues(OUT) queue snapshot entries that exist. + */ +struct kfd_ioctl_dbg_trap_queue_snapshot_args { + __u64 exception_mask; + __u64 snapshot_buf_ptr; + __u32 num_queues; + __u32 entry_size; +}; + +/** + * kfd_ioctl_dbg_trap_get_device_snapshot_args + * + * Arguments for KFD_IOC_DBG_TRAP_GET_DEVICE_SNAPSHOT + * Get device information. + * + * @exception_mask (IN) - exceptions raised to clear + * @snapshot_buf_ptr (IN) - pointer to snapshot buffer (see kfd_dbg_device_info_entry) + * @num_devices (IN/OUT) - number of debug devices to snapshot + * The debugger specifies the size of the array allocated in @num_devices. + * KFD returns the number of devices that actually existed. If this is + * larger than the size specified by the debugger, KFD will not overflow + * the array allocated by the debugger. + * + * @entry_size (IN/OUT) - size per entry in bytes + * The debugger specifies sizeof(struct kfd_dbg_device_info_entry) in + * @entry_size. KFD returns the number of bytes actually populated. The + * debugger should use KFD_IOCTL_MINOR_VERSION to determine, which fields + * in struct kfd_dbg_device_info_entry are valid. This allows growing the + * ABI in a backwards compatible manner. + * Note that entry_size(IN) should still be used to stride the snapshot buffer in the + * event that it's larger than actual kfd_dbg_device_info_entry. + * + * Generic errors apply (see kfd_dbg_trap_operations). + * Return - 0 on SUCCESS. + * Copies @num_devices(IN) device snapshot entries of size @entry_size(IN) + * into @snapshot_buf_ptr if @num_devices(IN) > 0. + * Otherwise return @num_devices(OUT) queue snapshot entries that exist. + */ +struct kfd_ioctl_dbg_trap_device_snapshot_args { + __u64 exception_mask; + __u64 snapshot_buf_ptr; + __u32 num_devices; + __u32 entry_size; +}; + +/** + * kfd_ioctl_dbg_trap_args + * + * Arguments to debug target process. + * + * @pid - target process to debug + * @op - debug operation (see kfd_dbg_trap_operations) + * + * @op determines which union struct args to use. + * Refer to kern docs for each kfd_ioctl_dbg_trap_*_args struct. + */ +struct kfd_ioctl_dbg_trap_args { + __u32 pid; + __u32 op; + + union { + struct kfd_ioctl_dbg_trap_enable_args enable; + struct kfd_ioctl_dbg_trap_send_runtime_event_args send_runtime_event; + struct kfd_ioctl_dbg_trap_set_exceptions_enabled_args set_exceptions_enabled; + struct kfd_ioctl_dbg_trap_set_wave_launch_override_args launch_override; + struct kfd_ioctl_dbg_trap_set_wave_launch_mode_args launch_mode; + struct kfd_ioctl_dbg_trap_suspend_queues_args suspend_queues; + struct kfd_ioctl_dbg_trap_resume_queues_args resume_queues; + struct kfd_ioctl_dbg_trap_set_node_address_watch_args set_node_address_watch; + struct kfd_ioctl_dbg_trap_clear_node_address_watch_args clear_node_address_watch; + struct kfd_ioctl_dbg_trap_set_flags_args set_flags; + struct kfd_ioctl_dbg_trap_query_debug_event_args query_debug_event; + struct kfd_ioctl_dbg_trap_query_exception_info_args query_exception_info; + struct kfd_ioctl_dbg_trap_queue_snapshot_args queue_snapshot; + struct kfd_ioctl_dbg_trap_device_snapshot_args device_snapshot; + }; +}; + +/** + * kfd_ioctl_pc_sample_op - PC Sampling ioctl operations + * + * @KFD_IOCTL_PCS_OP_QUERY_CAPABILITIES: Query device PC Sampling capabilities + * @KFD_IOCTL_PCS_OP_CREATE: Register this process with a per-device PC sampler instance + * @KFD_IOCTL_PCS_OP_DESTROY: Unregister from a previously registered PC sampler instance + * @KFD_IOCTL_PCS_OP_START: Process begins taking samples from a previously registered PC sampler instance + * @KFD_IOCTL_PCS_OP_STOP: Process stops taking samples from a previously registered PC sampler instance + */ +enum kfd_ioctl_pc_sample_op { + KFD_IOCTL_PCS_OP_QUERY_CAPABILITIES, + KFD_IOCTL_PCS_OP_CREATE, + KFD_IOCTL_PCS_OP_DESTROY, + KFD_IOCTL_PCS_OP_START, + KFD_IOCTL_PCS_OP_STOP, +}; + +/* Values have to be a power of 2*/ +#define KFD_IOCTL_PCS_FLAG_POWER_OF_2 0x00000001 + +enum kfd_ioctl_pc_sample_method { + KFD_IOCTL_PCS_METHOD_HOSTTRAP = 1, + KFD_IOCTL_PCS_METHOD_STOCHASTIC, +}; + +enum kfd_ioctl_pc_sample_type { + KFD_IOCTL_PCS_TYPE_TIME_US, + KFD_IOCTL_PCS_TYPE_CLOCK_CYCLES, + KFD_IOCTL_PCS_TYPE_INSTRUCTIONS +}; + +struct kfd_pc_sample_info { + __u64 interval; /* [IN] if PCS_TYPE_INTERVAL_US: sample interval in us + * if PCS_TYPE_CLOCK_CYCLES: sample interval in graphics core clk cycles + * if PCS_TYPE_INSTRUCTIONS: sample interval in instructions issued by + * graphics compute units + */ + __u64 interval_min; /* [OUT] */ + __u64 interval_max; /* [OUT] */ + __u64 flags; /* [OUT] indicate potential restrictions e.g FLAG_POWER_OF_2 */ + __u32 method; /* [IN/OUT] kfd_ioctl_pc_sample_method */ + __u32 type; /* [IN/OUT] kfd_ioctl_pc_sample_type */ +}; + +#define KFD_IOCTL_PCS_QUERY_TYPE_FULL (1 << 0) /* If not set, return current */ + +struct kfd_ioctl_pc_sample_args { + __u64 sample_info_ptr; /* array of kfd_pc_sample_info */ + __u32 num_sample_info; + __u32 op; /* kfd_ioctl_pc_sample_op */ + __u32 gpu_id; + __u32 trace_id; + __u32 flags; /* kfd_ioctl_pcs_query flags */ + __u32 version; +}; + #define AMDKFD_IOCTL_BASE 'K' #define AMDKFD_IO(nr) _IO(AMDKFD_IOCTL_BASE, nr) #define AMDKFD_IOR(nr, type) _IOR(AMDKFD_IOCTL_BASE, nr, type) @@ -659,45 +1677,44 @@ struct kfd_ioctl_cross_memory_copy_args { #define AMDKFD_IOC_WAIT_EVENTS \ AMDKFD_IOWR(0x0C, struct kfd_ioctl_wait_events_args) -#define AMDKFD_IOC_DBG_REGISTER \ +#define AMDKFD_IOC_DBG_REGISTER_DEPRECATED \ AMDKFD_IOW(0x0D, struct kfd_ioctl_dbg_register_args) -#define AMDKFD_IOC_DBG_UNREGISTER \ +#define AMDKFD_IOC_DBG_UNREGISTER_DEPRECATED \ AMDKFD_IOW(0x0E, struct kfd_ioctl_dbg_unregister_args) -#define AMDKFD_IOC_DBG_ADDRESS_WATCH \ +#define AMDKFD_IOC_DBG_ADDRESS_WATCH_DEPRECATED \ AMDKFD_IOW(0x0F, struct kfd_ioctl_dbg_address_watch_args) -#define AMDKFD_IOC_DBG_WAVE_CONTROL \ +#define AMDKFD_IOC_DBG_WAVE_CONTROL_DEPRECATED \ AMDKFD_IOW(0x10, struct kfd_ioctl_dbg_wave_control_args) #define AMDKFD_IOC_SET_SCRATCH_BACKING_VA \ AMDKFD_IOWR(0x11, struct kfd_ioctl_set_scratch_backing_va_args) -#define AMDKFD_IOC_GET_TILE_CONFIG \ +#define AMDKFD_IOC_GET_TILE_CONFIG \ AMDKFD_IOWR(0x12, struct kfd_ioctl_get_tile_config_args) #define AMDKFD_IOC_SET_TRAP_HANDLER \ AMDKFD_IOW(0x13, struct kfd_ioctl_set_trap_handler_args) -#define AMDKFD_IOC_GET_PROCESS_APERTURES_NEW \ - AMDKFD_IOWR(0x14, \ - struct kfd_ioctl_get_process_apertures_new_args) +#define AMDKFD_IOC_DBG_REGISTER_DEPRECATED \ + AMDKFD_IOW(0x0D, struct kfd_ioctl_dbg_register_args) -#define AMDKFD_IOC_ACQUIRE_VM \ - AMDKFD_IOW(0x15, struct kfd_ioctl_acquire_vm_args) +#define AMDKFD_IOC_DBG_UNREGISTER_DEPRECATED \ + AMDKFD_IOW(0x0E, struct kfd_ioctl_dbg_unregister_args) -#define AMDKFD_IOC_ALLOC_MEMORY_OF_GPU \ - AMDKFD_IOWR(0x16, struct kfd_ioctl_alloc_memory_of_gpu_args) +#define AMDKFD_IOC_DBG_ADDRESS_WATCH_DEPRECATED \ + AMDKFD_IOW(0x0F, struct kfd_ioctl_dbg_address_watch_args) -#define AMDKFD_IOC_FREE_MEMORY_OF_GPU \ - AMDKFD_IOW(0x17, struct kfd_ioctl_free_memory_of_gpu_args) +#define AMDKFD_IOC_DBG_WAVE_CONTROL_DEPRECATED \ + AMDKFD_IOW(0x10, struct kfd_ioctl_dbg_wave_control_args) #define AMDKFD_IOC_MAP_MEMORY_TO_GPU \ AMDKFD_IOWR(0x18, struct kfd_ioctl_map_memory_to_gpu_args) -#define AMDKFD_IOC_UNMAP_MEMORY_FROM_GPU \ - AMDKFD_IOWR(0x19, struct kfd_ioctl_unmap_memory_from_gpu_args) +#define AMDKFD_IOC_GET_TILE_CONFIG \ + AMDKFD_IOWR(0x12, struct kfd_ioctl_get_tile_config_args) #define AMDKFD_IOC_SET_CU_MASK \ AMDKFD_IOW(0x1A, struct kfd_ioctl_set_cu_mask_args) @@ -717,28 +1734,69 @@ struct kfd_ioctl_cross_memory_copy_args { #define AMDKFD_IOC_SMI_EVENTS \ AMDKFD_IOWR(0x1F, struct kfd_ioctl_smi_events_args) +#define AMDKFD_IOC_SVM AMDKFD_IOWR(0x20, struct kfd_ioctl_svm_args) + +#define AMDKFD_IOC_SET_XNACK_MODE \ + AMDKFD_IOWR(0x21, struct kfd_ioctl_set_xnack_mode_args) + +#define AMDKFD_IOC_CRIU_OP \ + AMDKFD_IOWR(0x22, struct kfd_ioctl_criu_args) + +#define AMDKFD_IOC_AVAILABLE_MEMORY \ + AMDKFD_IOWR(0x23, struct kfd_ioctl_get_available_memory_args) + +#define AMDKFD_IOC_EXPORT_DMABUF \ + AMDKFD_IOWR(0x24, struct kfd_ioctl_export_dmabuf_args) + +#define AMDKFD_IOC_RUNTIME_ENABLE \ + AMDKFD_IOWR(0x25, struct kfd_ioctl_runtime_enable_args) + +#define AMDKFD_IOC_DBG_TRAP \ + AMDKFD_IOWR(0x26, struct kfd_ioctl_dbg_trap_args) + +#define AMDKFD_IOC_SVM AMDKFD_IOWR(0x20, struct kfd_ioctl_svm_args) + +#define AMDKFD_IOC_SET_XNACK_MODE \ + AMDKFD_IOWR(0x21, struct kfd_ioctl_set_xnack_mode_args) + +#define AMDKFD_IOC_CRIU_OP \ + AMDKFD_IOWR(0x22, struct kfd_ioctl_criu_args) + +#define AMDKFD_IOC_AVAILABLE_MEMORY \ + AMDKFD_IOWR(0x23, struct kfd_ioctl_get_available_memory_args) + +#define AMDKFD_IOC_EXPORT_DMABUF \ + AMDKFD_IOWR(0x24, struct kfd_ioctl_export_dmabuf_args) + +#define AMDKFD_IOC_RUNTIME_ENABLE \ + AMDKFD_IOWR(0x25, struct kfd_ioctl_runtime_enable_args) + +#define AMDKFD_IOC_DBG_TRAP \ + AMDKFD_IOWR(0x26, struct kfd_ioctl_dbg_trap_args) + #define AMDKFD_COMMAND_START 0x01 -#define AMDKFD_COMMAND_END 0x20 +#define AMDKFD_COMMAND_END 0x27 /* non-upstream ioctls */ #define AMDKFD_IOC_IPC_IMPORT_HANDLE \ - AMDKFD_IOWR(0x1F, struct kfd_ioctl_ipc_import_handle_args) + AMDKFD_IOWR(0x80, struct kfd_ioctl_ipc_import_handle_args) #define AMDKFD_IOC_IPC_EXPORT_HANDLE \ - AMDKFD_IOWR(0x20, struct kfd_ioctl_ipc_export_handle_args) + AMDKFD_IOWR(0x81, struct kfd_ioctl_ipc_export_handle_args) -#define AMDKFD_IOC_DBG_TRAP \ - AMDKFD_IOWR(0x21, struct kfd_ioctl_dbg_trap_args) +#define AMDKFD_IOC_DBG_TRAP_DEPRECATED \ + AMDKFD_IOWR(0x82, struct kfd_ioctl_dbg_trap_args_deprecated) -#define AMDKFD_IOC_CROSS_MEMORY_COPY \ - AMDKFD_IOWR(0x22, struct kfd_ioctl_cross_memory_copy_args) +#define AMDKFD_IOC_CROSS_MEMORY_COPY_DEPRECATED \ + AMDKFD_IOWR(0x83, struct kfd_ioctl_cross_memory_copy_deprecated_args) +#define AMDKFD_IOC_RLC_SPM \ + AMDKFD_IOWR(0x84, struct kfd_ioctl_spm_args) -#define AMDKFD_IOC_AVAILABLE_MEMORY \ - AMDKFD_IOWR(0x23, struct kfd_ioctl_get_available_memory_args) +#define AMDKFD_IOC_PC_SAMPLE \ + AMDKFD_IOWR(0x85, struct kfd_ioctl_pc_sample_args) -#define AMDKFD_COMMAND_START 0x01 -#undef AMDKFD_COMMAND_END -#define AMDKFD_COMMAND_END 0x22 +#define AMDKFD_COMMAND_START_2 0x80 +#define AMDKFD_COMMAND_END_2 0x86 -#endif // INCLUDE_ROCM_SMI_KFD_IOCTL_H_ +#endif diff --git a/rocm_smi/include/rocm_smi/rocm_smi.h b/rocm_smi/include/rocm_smi/rocm_smi.h index 40b2180b51..f4c58b5bcc 100644 --- a/rocm_smi/include/rocm_smi/rocm_smi.h +++ b/rocm_smi/include/rocm_smi/rocm_smi.h @@ -344,9 +344,15 @@ typedef enum { RSMI_EVT_NOTIF_THERMAL_THROTTLE = KFD_SMI_EVENT_THERMAL_THROTTLE, RSMI_EVT_NOTIF_GPU_PRE_RESET = KFD_SMI_EVENT_GPU_PRE_RESET, RSMI_EVT_NOTIF_GPU_POST_RESET = KFD_SMI_EVENT_GPU_POST_RESET, - RSMI_EVT_NOTIF_RING_HANG = KFD_SMI_EVENT_RING_HANG, - - RSMI_EVT_NOTIF_LAST = RSMI_EVT_NOTIF_RING_HANG + RSMI_EVT_NOTIF_EVENT_MIGRATE_START = KFD_SMI_EVENT_MIGRATE_START, + RSMI_EVT_NOTIF_EVENT_MIGRATE_END = KFD_SMI_EVENT_MIGRATE_END, + RSMI_EVT_NOTIF_EVENT_PAGE_FAULT_START = KFD_SMI_EVENT_PAGE_FAULT_START, + RSMI_EVT_NOTIF_EVENT_PAGE_FAULT_END = KFD_SMI_EVENT_PAGE_FAULT_END, + RSMI_EVT_NOTIF_EVENT_QUEUE_EVICTION = KFD_SMI_EVENT_QUEUE_EVICTION, + RSMI_EVT_NOTIF_EVENT_QUEUE_RESTORE = KFD_SMI_EVENT_QUEUE_RESTORE, + RSMI_EVT_NOTIF_EVENT_UNMAP_FROM_GPU = KFD_SMI_EVENT_UNMAP_FROM_GPU, + RSMI_EVT_NOTIF_EVENT_ALL_PROCESS = KFD_SMI_EVENT_ALL_PROCESS, + RSMI_EVT_NOTIF_LAST = KFD_SMI_EVENT_ALL_PROCESS } rsmi_evt_notification_type_t; /** @@ -355,7 +361,8 @@ typedef enum { #define RSMI_EVENT_MASK_FROM_INDEX(i) (1ULL << ((i) - 1)) //! Maximum number of characters an event notification message will be -#define MAX_EVENT_NOTIFICATION_MSG_SIZE 64 +// matches kfd message max size +#define MAX_EVENT_NOTIFICATION_MSG_SIZE 96 /** * Event notification data returned from event notification API @@ -1264,7 +1271,7 @@ typedef struct { /** * Accumulated throttler residencies * - * Socket (thermal) - + * Socket (thermal) - * Socket thermal violation % (greater than 0% is a violation); * aka TVIOL * diff --git a/rocm_smi/include/rocm_smi/rocm_smi_utils.h b/rocm_smi/include/rocm_smi/rocm_smi_utils.h index 18cfce0d9b..e86780ee3f 100644 --- a/rocm_smi/include/rocm_smi/rocm_smi_utils.h +++ b/rocm_smi/include/rocm_smi/rocm_smi_utils.h @@ -427,7 +427,7 @@ class TagTextContents_t decltype(auto) get_structured_data_subkey_last(const PrimaryKeyType& prim_key) { return (get_structured_value_by_keys(prim_key, get_structured_data_subkey_by_position(prim_key, - (get_structured_subkeys_size(prim_key) - 1)))); + static_cast((get_structured_subkeys_size(prim_key) - 1))))); } void reset() { diff --git a/rocm_smi/src/rocm_smi.cc b/rocm_smi/src/rocm_smi.cc index 5f36e8d256..2a4b6d1aae 100644 --- a/rocm_smi/src/rocm_smi.cc +++ b/rocm_smi/src/rocm_smi.cc @@ -186,39 +186,6 @@ static uint64_t freq_string_to_int(const std::vector &freq_lines, return static_cast(freq*multiplier); } -static void freq_volt_string_to_point(std::string in_line, - rsmi_od_vddc_point_t *pt) { - std::istringstream fs_vlt(in_line); - - assert(pt != nullptr); - THROW_IF_NULLPTR_DEREF(pt) - - uint32_t ind; - float freq; - float volts; - std::string junk; - std::string freq_units_str; - std::string volts_units_str; - - fs_vlt >> ind; - fs_vlt >> junk; // colon - fs_vlt >> freq; - fs_vlt >> freq_units_str; - fs_vlt >> volts; - fs_vlt >> volts_units_str; - - if (freq < 0) { - throw amd::smi::rsmi_exception(RSMI_STATUS_UNEXPECTED_SIZE, __FUNCTION__); - } - - long double multiplier = get_multiplier_from_str(freq_units_str[0]); - - pt->frequency = static_cast(freq*multiplier); - - multiplier = get_multiplier_from_str(volts_units_str[0]); - pt->voltage = static_cast(volts*multiplier); -} - static void od_value_pair_str_to_range(std::string in_line, rsmi_range_t *rg) { std::istringstream fs_rng(in_line); @@ -898,7 +865,7 @@ rsmi_status_t rsmi_ras_feature_info_get( auto eeprom_version = strtoul( feature_line.substr(strlen(version_key)).c_str(), nullptr, 16); if (errno == 0) { - ras_feature->ras_eeprom_version = eeprom_version; + ras_feature->ras_eeprom_version = static_cast(eeprom_version); } else { return RSMI_STATUS_NOT_SUPPORTED; } @@ -922,7 +889,7 @@ rsmi_status_t rsmi_ras_feature_info_get( auto schema = strtoul( feature_line.substr(strlen(schema_key)).c_str(), nullptr, 16); if (errno == 0) { - ras_feature->ecc_correction_schema_flag = schema; + ras_feature->ecc_correction_schema_flag = static_cast(schema); } else { return RSMI_STATUS_NOT_SUPPORTED; } @@ -2044,7 +2011,7 @@ rsmi_dev_gpu_clk_freq_set(uint32_t dv_ind, // will have read-only perms, and the OS will deny access, before the request hits the driver level if (status == RSMI_STATUS_PERMISSION){ bool read_only = false; - int perms = amd::smi::isReadOnlyForAll(dev->path(), &read_only); + amd::smi::isReadOnlyForAll(dev->path(), &read_only); if(read_only){ return RSMI_STATUS_NOT_SUPPORTED; } @@ -2113,8 +2080,6 @@ rsmi_status_t rsmi_dev_process_isolation_get(uint32_t dv_ind, rsmi_status_t rsmi_dev_process_isolation_set(uint32_t dv_ind, uint32_t pisolate) { - rsmi_status_t ret; - TRY std::ostringstream ss; ss << __PRETTY_FUNCTION__ << " | ======= start ======="; @@ -2178,8 +2143,6 @@ rsmi_status_t rsmi_dev_process_isolation_set(uint32_t dv_ind, } rsmi_status_t rsmi_dev_gpu_run_cleaner_shader(uint32_t dv_ind) { - rsmi_status_t ret; - TRY std::ostringstream ss; ss << __PRETTY_FUNCTION__ << " | ======= start ======="; @@ -2294,8 +2257,6 @@ rsmi_dev_xgmi_plpd_get(uint32_t dv_ind, rsmi_status_t rsmi_dev_xgmi_plpd_set(uint32_t dv_ind, uint32_t plpd_id) { - rsmi_status_t ret; - TRY std::ostringstream ss; ss << __PRETTY_FUNCTION__ << " | ======= start ======="; @@ -2408,8 +2369,6 @@ rsmi_dev_soc_pstate_get(uint32_t dv_ind, rsmi_status_t rsmi_dev_soc_pstate_set(uint32_t dv_ind, uint32_t policy_id) { - rsmi_status_t ret; - TRY std::ostringstream ss; ss << __PRETTY_FUNCTION__ << " | ======= start ======="; @@ -2977,25 +2936,25 @@ rsmi_dev_pci_bandwidth_get(uint32_t dv_ind, rsmi_pcie_bandwidth_t *b) { return ret; } - // Hardcode based on PCIe specification: Search PCI_Express on wikipedia + // Hardcode based on PCIe specification: search PCI_Express on wikipedia const uint32_t link_width[] = {1, 2, 4, 8, 12, 16}; const uint32_t link_speed[] = {25, 50, 80, 160}; // 0.1 Ghz const uint32_t WIDTH_DATA_LENGTH = sizeof(link_width)/sizeof(uint32_t); const uint32_t SPEED_DATA_LENGTH = sizeof(link_speed)/sizeof(uint32_t); // Calculate the index - uint32_t width_index = -1; - uint32_t speed_index = -1; + int32_t width_index = -1; + int32_t speed_index = -1; uint32_t cur_index = 0; for (cur_index = 0; cur_index < WIDTH_DATA_LENGTH; cur_index++) { if (link_width[cur_index] == gpu_metrics.pcie_link_width) { - width_index = cur_index; + width_index = static_cast(cur_index); break; } } for (cur_index = 0; cur_index < SPEED_DATA_LENGTH; cur_index++) { if (link_speed[cur_index] == gpu_metrics.pcie_link_speed) { - speed_index = cur_index; + speed_index = static_cast(cur_index); break; } } @@ -3004,7 +2963,7 @@ rsmi_dev_pci_bandwidth_get(uint32_t dv_ind, rsmi_pcie_bandwidth_t *b) { } // Set possible lanes and frequencies b->transfer_rate.num_supported = WIDTH_DATA_LENGTH * SPEED_DATA_LENGTH; - b->transfer_rate.current = speed_index*WIDTH_DATA_LENGTH + width_index; + b->transfer_rate.current = static_cast(speed_index)*WIDTH_DATA_LENGTH + static_cast(width_index); for (cur_index = 0; cur_index < WIDTH_DATA_LENGTH * SPEED_DATA_LENGTH; cur_index++) { b->transfer_rate.frequency[cur_index] = static_cast(link_speed[cur_index/WIDTH_DATA_LENGTH]) * 100 * 1000000L; @@ -3930,7 +3889,6 @@ rsmi_dev_memory_total_get(uint32_t dv_ind, rsmi_memory_type_t mem_type, rsmi_status_t rsmi_dev_cache_info_get( uint32_t dv_ind, rsmi_gpu_cache_info_t *info) { TRY - rsmi_status_t ret; std::ostringstream ss; ss << __PRETTY_FUNCTION__ << "| ======= start ======="; LOG_TRACE(ss); @@ -4214,7 +4172,6 @@ rsmi_utilization_count_get(uint32_t dv_ind, rsmi_status_t ret; rsmi_gpu_metrics_t gpu_metrics; - uint32_t val_ui32; uint16_t val_counter(0); ret = rsmi_dev_gpu_metrics_info_get(dv_ind, &gpu_metrics); @@ -5704,10 +5661,6 @@ rsmi_dev_memory_partition_set(uint32_t dv_ind, REQUIRE_ROOT_ACCESS DEVICE_MUTEX const int k1000_MS_WAIT = 1000; - const uint32_t kMaxBoardLength = 128; - bool isCorrectDevice = false; - char boardName[kMaxBoardLength]; - boardName[0] = '\0'; const uint32_t kMaxMemoryCapabilitiesSize = 30; char available_memory_capabilities[kMaxMemoryCapabilitiesSize]; @@ -6618,16 +6571,230 @@ rsmi_event_notification_get(int timeout_ms, reinterpret_cast(&data[*num_elem]); uint32_t event; - while (fscanf(anon_fp, "%x %63s\n", &event, - reinterpret_cast(&data_item->message)) == 2) { - /* Output is in format as "event information\n" + char event_in[MAX_EVENT_NOTIFICATION_MSG_SIZE]; + memcpy(reinterpret_cast(event_in), "\0", MAX_EVENT_NOTIFICATION_MSG_SIZE); + while (fgets(event_in, MAX_EVENT_NOTIFICATION_MSG_SIZE, anon_fp)) { + /* Output is in format as "event_number message_information\n" * Both event are expressed in hex. * information is a string */ + char message[MAX_EVENT_NOTIFICATION_MSG_SIZE]; + // parse the line here for event_number and rest of message_information + sscanf(event_in, "%x %[^\n]\n", &event, message); + + // parse message based on event received + switch (event){ + case RSMI_EVT_NOTIF_NONE: + strcpy(reinterpret_cast(&data_item->message), "Event type None received"); + break; + case RSMI_EVT_NOTIF_VMFAULT: + { + uint32_t pid; + char task_name[MAX_EVENT_NOTIFICATION_MSG_SIZE]; + memcpy(reinterpret_cast(task_name), "\0", MAX_EVENT_NOTIFICATION_MSG_SIZE); + + sscanf(message, "%x:%s\n", &pid, task_name); + std::stringstream final_message; + final_message << "PID: " << std::to_string(pid).c_str() + << " task name: " << task_name; + + strcpy(reinterpret_cast(&data_item->message), final_message.str().c_str()); + } + break; + case RSMI_EVT_NOTIF_THERMAL_THROTTLE: + { + uint64_t bitmask; + uint64_t counter; + + sscanf(message, "%llx:%llx\n", &bitmask, &counter); + std::stringstream final_message; + final_message << "bitmask: 0x" << std::hex << bitmask + << " counter: 0x" << std::hex << counter; + + strcpy(reinterpret_cast(&data_item->message), final_message.str().c_str()); + } + break; + case RSMI_EVT_NOTIF_GPU_PRE_RESET: + { + uint32_t reset_seq_num; + char reset_cause[MAX_EVENT_NOTIFICATION_MSG_SIZE]; + memcpy(reinterpret_cast(reset_cause), "\0", MAX_EVENT_NOTIFICATION_MSG_SIZE); + + sscanf(message, "%x %[^\n]\n", &reset_seq_num, reset_cause); + std::stringstream final_message; + final_message << "reset sequence number: " << std::to_string(reset_seq_num).c_str() + << " reset cause: " << reset_cause; + + strcpy(reinterpret_cast(&data_item->message), final_message.str().c_str()); + } + break; + case RSMI_EVT_NOTIF_GPU_POST_RESET: + { + uint32_t reset_seq_num; + + sscanf(message, "%x %[^\n]\n", &reset_seq_num); + std::stringstream final_message; + final_message << "reset sequence number: " << std::to_string(reset_seq_num).c_str(); + + strcpy(reinterpret_cast(&data_item->message), final_message.str().c_str()); + } + break; + case RSMI_EVT_NOTIF_EVENT_MIGRATE_START: + { + int64_t ns; + int32_t pid; + uint32_t start; + uint32_t size; + uint16_t from; + uint16_t to; + uint16_t prefetch_loc; + uint16_t preferred_loc; + int32_t migrate_trigger; + + sscanf(message, "%lld -%d @%lx(%lx) %x->%x %x:%x %d\n", &ns, &pid, &start, &size, &from, &to, &prefetch_loc, &preferred_loc, &migrate_trigger); + std::stringstream final_message; + final_message << "nd: " << std::to_string(ns).c_str() + << " pid: " << std::to_string(pid).c_str() + << " start: 0x" << std::hex << start + << " size: 0x" << std::hex << size + << " from: 0x" << std::hex << from + << " to: 0x" << std::hex << to + << " prefetch_loc: 0x" << std::hex << prefetch_loc + << " preferred_loc: 0x" << std::hex << preferred_loc + << " migrate_trigger: " << std::to_string(migrate_trigger).c_str(); + + strcpy(reinterpret_cast(&data_item->message), final_message.str().c_str()); + } + break; + case RSMI_EVT_NOTIF_EVENT_MIGRATE_END: + { + int64_t ns; + int32_t pid; + uint32_t start; + uint32_t size; + uint32_t from; + uint32_t to; + uint32_t migrate_trigger; + uint32_t error_code; + + sscanf(message, "%lld -%d @%lx(%lx) %x->%x %d %d\n", &ns, &pid, &start, &size, &from, &to, &migrate_trigger, &error_code); + std::stringstream final_message; + final_message << "nd: " << std::to_string(ns).c_str() + << " pid: " << std::to_string(pid).c_str() + << " start: 0x" << std::hex << start + << " size: 0x" << std::hex << size + << " from: 0x" << std::hex << from + << " to: 0x" << std::hex << to + << " migrate_trigger: " << std::to_string(migrate_trigger).c_str() + << " error_code: " << std::to_string(error_code).c_str(); + + strcpy(reinterpret_cast(&data_item->message), final_message.str().c_str()); + } + break; + case RSMI_EVT_NOTIF_EVENT_PAGE_FAULT_START: + { + int64_t ns; + int32_t pid; + uint32_t addr; + uint32_t node; + char *rw; + + sscanf(message, "%lld -%d @%lx(%x) %c\n", &ns, &pid, &addr, &node, rw); + std::stringstream final_message; + final_message << "ns: " << std::to_string(ns).c_str() + << " pid: " << std::to_string(pid).c_str() + << " addr: 0x" << std::hex << addr + << " node: 0x" << std::hex << node + << " rw: " << rw; + + strcpy(reinterpret_cast(&data_item->message), final_message.str().c_str()); + } + break; + case RSMI_EVT_NOTIF_EVENT_PAGE_FAULT_END: + { + int64_t ns; + int32_t pid; + uint32_t addr; + uint32_t node; + char *migrate_update; + + sscanf(message, "%lld -%d @%lx(%x) %c\n", &ns, &pid, &addr, &node, migrate_update); + std::stringstream final_message; + final_message << "ns: " << std::to_string(ns).c_str() + << " pid: " << std::to_string(pid).c_str() + << " addr: 0x" << std::hex << addr + << " node: 0x" << std::hex << node + << " migrate_udpate: " << migrate_update; + + strcpy(reinterpret_cast(&data_item->message), final_message.str().c_str()); + } + break; + case RSMI_EVT_NOTIF_EVENT_QUEUE_EVICTION: + { + int64_t ns; + int32_t pid; + uint32_t node; + uint32_t evict_trigger; + + sscanf(message, "%lld -%d %x %d\n", &ns, &pid, &node, &evict_trigger); + std::stringstream final_message; + final_message << "ns: " << std::to_string(ns).c_str() + << " pid: " << std::to_string(pid).c_str() + << " node: 0x" << std::hex << node + << " evict_trigger: " << std::to_string(evict_trigger).c_str(); + + strcpy(reinterpret_cast(&data_item->message), final_message.str().c_str()); + } + break; + case RSMI_EVT_NOTIF_EVENT_QUEUE_RESTORE: + { + int64_t ns; + int32_t pid; + uint32_t node; + char *rescheduled; + + sscanf(message, "%lld -%d %x %c\n", &ns, &pid, &node, rescheduled); + std::stringstream final_message; + final_message << "ns: " << std::to_string(ns).c_str() + << " pid: " << std::to_string(pid).c_str() + << " node: 0x" << std::hex << node + << " rescheduled: " << rescheduled; + + strcpy(reinterpret_cast(&data_item->message), final_message.str().c_str()); + } + break; + case RSMI_EVT_NOTIF_EVENT_UNMAP_FROM_GPU: + { + int64_t ns; + int32_t pid; + uint32_t addr; + uint32_t size; + uint32_t node; + uint32_t unmap_trigger; + + sscanf(message, "%lld -%d @%lx(%lx) %x %d\n", &ns, &pid, &addr, &size, &node, &unmap_trigger); + std::stringstream final_message; + final_message << "ns: " << std::to_string(ns).c_str() + << " pid: " << std::to_string(pid).c_str() + << " addr: 0x" <(&data_item->message), final_message.str().c_str()); + } + break; + default: + strcpy(reinterpret_cast(&data_item->message), "Unknown event received"); + break; + } data_item->event = (rsmi_evt_notification_type_t)event; data_item->dv_ind = fd_indx_to_dev_id[i]; ++(*num_elem); + // zero out event_in after each use + memcpy(reinterpret_cast(event_in), "\0", MAX_EVENT_NOTIFICATION_MSG_SIZE); + if (*num_elem >= buffer_size) { break; } diff --git a/rocm_smi/src/rocm_smi_binary_parser.cc b/rocm_smi/src/rocm_smi_binary_parser.cc index 36100ae738..2b6a660cd7 100644 --- a/rocm_smi/src/rocm_smi_binary_parser.cc +++ b/rocm_smi/src/rocm_smi_binary_parser.cc @@ -30,6 +30,7 @@ #include "rocm_smi/rocm_smi_logger.h" #include +#include #include #include @@ -134,7 +135,7 @@ int present_pmmetrics(const char* fname, } table = NULL; - len = fread(buf1, 1, 65536, infile); + len = static_cast(fread(buf1, 1, 65536, infile)); fseek(infile, 0, SEEK_SET); memcpy(&pmmetrics_version, &buf1[12], 4); @@ -156,11 +157,11 @@ int present_pmmetrics(const char* fname, static int parse_reg_state_table(uint8_t *buf, int32_t buflen, struct metric_field *table, rsmi_name_value_t **kv, uint32_t *kvnum) { - int skip_smn, x, y, cur_instance, cur_smn, - num_instance, num_smn, instance_start, smn_start; + uint64_t skip_smn, x, y, cur_instance, cur_smn, + num_instance, num_smn, instance_start, smn_start; uint64_t v; uint8_t *obuf, *origbuf; - int kvsize = 64; + uint32_t kvsize = 64; *kv = reinterpret_cast(calloc(kvsize, sizeof **kv)); *kvnum = 0; @@ -171,7 +172,7 @@ static int parse_reg_state_table(uint8_t *buf, int32_t buflen, origbuf = buf; top: while (table[x].field_name != NULL) { - for (y = 0; y < table[x].field_arr_size; y++) { + for (y = 0; y < static_cast(table[x].field_arr_size); y++) { obuf = buf; v = get_value(&buf, &table[x]); if ((intptr_t)(buf - origbuf) > buflen) { @@ -203,10 +204,10 @@ top: } break; case FIELD_FLAG_NUM_INSTANCE: - num_instance = v; + num_instance = static_cast(v); break; case FIELD_FLAG_NUM_SMN: - num_smn = v; + num_smn = static_cast(v); if (v) skip_smn = 0; else @@ -220,12 +221,12 @@ top: } sprintf((*kv)[*kvnum].name, "%s", table[x].field_name); if (table[x].field_arr_size > 1) { - sprintf((*kv)[*kvnum].name + strlen((*kv)[*kvnum].name), "[%d]", y); + sprintf((*kv)[*kvnum].name + strlen((*kv)[*kvnum].name), "[%" PRId64 "]", y); } if (x >= instance_start) - sprintf((*kv)[*kvnum].name + strlen((*kv)[*kvnum].name), ".instance[%d]", cur_instance); + sprintf((*kv)[*kvnum].name + strlen((*kv)[*kvnum].name), ".instance[%" PRId64 "]", cur_instance); if (x >= smn_start) - sprintf((*kv)[*kvnum].name + strlen((*kv)[*kvnum].name), ".smn[%d]", cur_smn); + sprintf((*kv)[*kvnum].name + strlen((*kv)[*kvnum].name), ".smn[%" PRId64 "]", cur_smn); (*kv)[*kvnum].value = v; ++(*kvnum); } @@ -290,7 +291,7 @@ int present_reg_state(const char* fname, return -2; } - len = fread(buf, 1, sizeof buf, infile); + len = static_cast(fread(buf, 1, sizeof buf, infile)); fclose(infile); return parse_reg_state_table(buf, len, tab, kv, kvnum); } diff --git a/rocm_smi/src/rocm_smi_device.cc b/rocm_smi/src/rocm_smi_device.cc index 7621d2819c..6715cfa6d4 100644 --- a/rocm_smi/src/rocm_smi_device.cc +++ b/rocm_smi/src/rocm_smi_device.cc @@ -1474,7 +1474,6 @@ rsmi_status_t Device::restartAMDGpuDriver(void) { bool success = false; std::string out; bool wasGdmServiceActive = false; - bool restartInProgress = true; bool isRestartInProgress = true; bool isAMDGPUModuleLive = false; bool restartGDM = false; @@ -1560,7 +1559,6 @@ rsmi_status_t Device::isRestartInProgress(bool *isRestartInProgress, bool *isAMDGPUModuleLive) { REQUIRE_ROOT_ACCESS std::ostringstream ss; - bool restartSuccessful = true; bool success = false; std::string out; bool deviceRestartInProgress = true; // Assume in progress, we intend to disprove diff --git a/rocm_smi/src/rocm_smi_gpu_metrics.cc b/rocm_smi/src/rocm_smi_gpu_metrics.cc index 69946ac8a6..b7443652bd 100644 --- a/rocm_smi/src/rocm_smi_gpu_metrics.cc +++ b/rocm_smi/src/rocm_smi_gpu_metrics.cc @@ -63,7 +63,7 @@ namespace amd::smi constexpr uint16_t join_metrics_version(uint8_t format_rev, uint8_t content_rev) { - return (format_rev << 8 | content_rev); + return static_cast((format_rev << 8 | content_rev)); } constexpr uint16_t join_metrics_version(const AMDGpuMetricsHeader_v1_t& metrics_header) @@ -473,8 +473,8 @@ AMDGpuDynamicMetricTblValues_t format_metric_row(const T& metric, const std::str void GpuMetricsBase_v16_t::dump_internal_metrics_table() { std::ostringstream ss; - auto idx = uint64_t(0); - auto idy = uint64_t(0); + auto idx = int64_t(0); + auto idy = int64_t(0); std::cout << __PRETTY_FUNCTION__ << " | ======= start ======= \n"; ss << __PRETTY_FUNCTION__ << " | ======= DEBUG ======= " @@ -570,9 +570,16 @@ void GpuMetricsBase_v16_t::dump_internal_metrics_table() } for (auto& col : row.gfx_busy_inst) { ss << "\t [" << idx << "] [" << idy << "]: " << col; +#if 1 // TODO: Refactor this code using make_ostream_joiner + // Do for all occurences in this file if (idy + 1 != (std::end(row.gfx_busy_inst) - std::end(row.gfx_busy_inst) - 1)) { ss << ", "; } +#else + std::copy(std::begin(row.gfx_busy_inst), + std::end(row.gfx_busy_inst), + amd::smi::make_ostream_joiner(&ss, ", ")); +#endif if (idx + 1 != (std::end(m_gpu_metrics_tbl.m_xcp_stats) - std::end(m_gpu_metrics_tbl.m_xcp_stats) - 1)) { ss << "\n"; @@ -4024,7 +4031,7 @@ rsmi_dev_gpu_metrics_info_get(uint32_t dv_ind, rsmi_gpu_metrics_t* smu) { dev->set_smi_device_id(dv_ind); uint32_t partition_id = 0; - auto ret = rsmi_dev_partition_id_get(dv_ind, &partition_id); + rsmi_dev_partition_id_get(dv_ind, &partition_id); dev->set_smi_partition_id(partition_id); dev->dev_log_gpu_metrics(ostrstream); const auto [error_code, external_metrics] = dev->dev_copy_internal_to_external_metrics(); diff --git a/rocm_smi/src/rocm_smi_kfd.cc b/rocm_smi/src/rocm_smi_kfd.cc index 558c7e7660..18c060337a 100644 --- a/rocm_smi/src/rocm_smi_kfd.cc +++ b/rocm_smi/src/rocm_smi_kfd.cc @@ -879,7 +879,7 @@ int KFDNode::get_used_memory(uint64_t* used) { return 1; } struct kfd_ioctl_get_available_memory_args mem = {0, 0, 0}; - mem.gpu_id = gpu_id_; + mem.gpu_id = static_cast(gpu_id_); if (ioctl(kfd_fd, AMDKFD_IOC_AVAILABLE_MEMORY , &mem) != 0) { close(kfd_fd); return 1; @@ -925,8 +925,7 @@ int KFDNode::get_cache_info(rsmi_gpu_cache_info_t *info) { // num_cu_shared – this can be fetched by counting the number of 1’s in the sibling_map. std::string sibling_map = get_properties_from_file(prop_file, "sibling_map "); - uint32_t num_cu_shared = - std::count(sibling_map.begin(), sibling_map.end(), '1'); + uint32_t num_cu_shared = static_cast(std::count(sibling_map.begin(), sibling_map.end(), '1')); // known cache type bool is_count_already = false; diff --git a/rocm_smi/src/rocm_smi_main.cc b/rocm_smi/src/rocm_smi_main.cc index 7d72a96789..d0d1394221 100644 --- a/rocm_smi/src/rocm_smi_main.cc +++ b/rocm_smi/src/rocm_smi_main.cc @@ -755,10 +755,9 @@ uint32_t RocmSMI::DiscoverAmdgpuDevices(void) { int ret_unique_id = read_node_properties(node_id, "unique_id", &unique_id); int ret_loc_id = read_node_properties(node_id, "location_id", &location_id); - int ret_domain = - read_node_properties(node_id, "domain", &domain); + read_node_properties(node_id, "domain", &domain); if (ret_gpu_id == 0 && - ~(ret_unique_id != 0 || ret_loc_id != 0 || ret_unique_id != 0)) { + !(ret_unique_id != 0 || ret_loc_id != 0 || ret_unique_id != 0)) { // Do not try to build a node if one of these fields // do not exist in KFD (0 as values okay) systemNode myNode; @@ -804,7 +803,7 @@ uint32_t RocmSMI::DiscoverAmdgpuDevices(void) { uint32_t cardAdded = 0; // Discover all root cards & gpu partitions associated with each - for (uint32_t cardId = 0; cardId <= max_cardId; cardId++) { + for (int32_t cardId = 0; cardId <= max_cardId; cardId++) { std::string path = kPathDRMRoot; path += "/card"; path += std::to_string(cardId); @@ -917,7 +916,6 @@ uint32_t RocmSMI::DiscoverAmdgpuDevices(void) { LOG_DEBUG(ss); uint64_t temp_primary_unique_id = 0; - uint64_t primary_location_id = 0; if (allSystemNodes.empty()) { cardAdded++; ss << __PRETTY_FUNCTION__ @@ -966,7 +964,7 @@ uint32_t RocmSMI::DiscoverAmdgpuDevices(void) { } else { cardAdded++; // remove already added nodes associated with current card - auto erasedNodes = allSystemNodes.erase(0); + allSystemNodes.erase(0); continue; } @@ -988,7 +986,6 @@ uint32_t RocmSMI::DiscoverAmdgpuDevices(void) { auto removalLocId = it->second.s_location_id; auto removaldomain = it->second.s_domain; auto nodesErased = 1; - primary_location_id = removalLocId; allSystemNodes.erase(it++); ss << __PRETTY_FUNCTION__ << "\nPRIMARY --> num_nodes == temp_numb_nodes; ERASING " diff --git a/rocm_smi/src/rocm_smi_utils.cc b/rocm_smi/src/rocm_smi_utils.cc index 0f31a5b69e..0dafa5795a 100644 --- a/rocm_smi/src/rocm_smi_utils.cc +++ b/rocm_smi/src/rocm_smi_utils.cc @@ -1090,6 +1090,7 @@ std::string splitString(std::string str, char delim) { tokens.push_back(token); return token; // return 1st match } + return ""; } static std::string pt_rng_Mhz(std::string title, rsmi_range *r) { @@ -1118,26 +1119,6 @@ static std::string pt_rng_mV(std::string title, rsmi_range *r) { return ss.str(); } -static std::string print_pnt(rsmi_od_vddc_point_t *pt) { - std::ostringstream ss; - ss << "\t\t** Frequency: " << pt->frequency/1000000 << " MHz\n"; - ss << "\t\t** Voltage: " << pt->voltage << " mV\n"; - return ss.str(); -} - -static std::string pt_vddc_curve(rsmi_od_volt_curve *c) { - std::ostringstream ss; - if (c == nullptr) { - ss << "pt_vddc_curve | rsmi_od_volt_curve c = nullptr\n"; - return ss.str(); - } - - for (uint32_t i = 0; i < RSMI_NUM_VOLTAGE_CURVE_POINTS; ++i) { - ss << print_pnt(&c->vc_points[i]); - } - return ss.str(); -} - std::string print_rsmi_od_volt_freq_data_t(rsmi_od_volt_freq_data_t *odv) { std::ostringstream ss; if (odv == nullptr) { @@ -1242,7 +1223,7 @@ rsmi_status_t rsmi_dev_number_of_computes_get(uint32_t dv_ind, uint32_t* num_com return rsmi_status_t::RSMI_STATUS_NOT_SUPPORTED; } - *num_computes = (tmp_simd_count / tmp_simd_per_cu); + *num_computes = static_cast((tmp_simd_count / tmp_simd_per_cu)); return rsmi_status_t::RSMI_STATUS_SUCCESS; } @@ -1296,7 +1277,7 @@ void system_wait(int milli_seconds) { } int countDigit(uint64_t n) { - return static_cast(std::floor(log10(n) + 1)); + return static_cast(std::floor(log10(static_cast(n)) + 1)); } } // namespace smi diff --git a/src/amd_smi/amd_smi.cc b/src/amd_smi/amd_smi.cc index 2f5cfd3821..6d48476128 100644 --- a/src/amd_smi/amd_smi.cc +++ b/src/amd_smi/amd_smi.cc @@ -1020,8 +1020,9 @@ amdsmi_get_gpu_asic_info(amdsmi_processor_handle processor_handle, amdsmi_asic_i // If vendor name is empty and the vendor id is 0x1002, set vendor name to AMD vendor string if ((info->vendor_name != NULL && info->vendor_name[0] == '\0') && info->vendor_id == 0x1002) { - memset(info->vendor_name, 0, 38); - strncpy(info->vendor_name, "Advanced Micro Devices Inc. [AMD/ATI]", 37); + std::string amd_name = "Advanced Micro Devices Inc. [AMD/ATI]"; + memset(info->vendor_name, 0, amd_name.size()+1); + strncpy(info->vendor_name, amd_name.c_str(), amd_name.size()+1); } // default to 0xffff as not supported @@ -1506,7 +1507,6 @@ amdsmi_get_gpu_accelerator_partition_profile(amdsmi_processor_handle processor_h // TODO(amdsmi_team): add resources here ^ auto tmp_partition_id = uint32_t(0); - auto tmp_xcd_count = uint16_t(0); amdsmi_status_t status = AMDSMI_STATUS_NOT_SUPPORTED; status = rsmi_wrapper(rsmi_dev_partition_id_get, processor_handle, &tmp_partition_id); @@ -2196,7 +2196,7 @@ amdsmi_get_clock_info(amdsmi_processor_handle processor_handle, amdsmi_clk_type_ } info->max_clk = max_freq; info->min_clk = min_freq; - info->clk_deep_sleep = sleep_state_freq; + info->clk_deep_sleep = static_cast(sleep_state_freq); switch (clk_type) { case AMDSMI_CLK_TYPE_GFX: @@ -2217,6 +2217,13 @@ amdsmi_get_clock_info(amdsmi_processor_handle processor_handle, amdsmi_clk_type_ case AMDSMI_CLK_TYPE_DCLK1: info->clk = metrics.current_dclk1; break; + case AMDSMI_CLK_TYPE_SOC: + info->clk = metrics.current_socclk; + break; + // fclk/df not supported by gpu metrics so providing default value which cannot be contrued to be valid + case AMDSMI_CLK_TYPE_DF: + info->clk = UINT32_MAX; + break; default: return AMDSMI_STATUS_INVAL; } @@ -2486,7 +2493,6 @@ amdsmi_get_gpu_device_uuid(amdsmi_processor_handle processor_handle, unsigned in amdsmi_status_t status = AMDSMI_STATUS_SUCCESS; SMIGPUDEVICE_MUTEX(gpu_device->get_mutex()) - size_t len = AMDSMI_GPU_UUID_SIZE; amdsmi_asic_info_t asic_info = {}; const uint8_t fcn = 0xff; @@ -2549,7 +2555,7 @@ amdsmi_status_t amdsmi_get_pcie_info(amdsmi_processor_handle processor_handle, a } // pcie speed in sysfs returns in GT/s - info->pcie_static.max_pcie_speed = pcie_speed * 1000; + info->pcie_static.max_pcie_speed = static_cast(pcie_speed * 1000); switch (info->pcie_static.max_pcie_speed) { case 2500: @@ -2715,8 +2721,6 @@ amdsmi_get_link_topology_nearest(amdsmi_processor_handle processor_handle, auto status(amdsmi_status_t::AMDSMI_STATUS_SUCCESS); - constexpr auto kKFD_CRAT_INTRA_SOCKET_WEIGHT = uint32_t(13); - constexpr auto kKFD_CRAT_XGMI_WEIGHT = uint32_t(15); /* * Note: This will need to be eventually consolidated within a unique link type. @@ -2759,7 +2763,6 @@ amdsmi_get_link_topology_nearest(amdsmi_processor_handle processor_handle, uint64_t link_weight; }; - using LinkTopogyOrderPair_t = std::pair; /* * Note: The link topology table is sorted by the number of hops and link weight. */ @@ -2815,7 +2818,6 @@ amdsmi_get_link_topology_nearest(amdsmi_processor_handle processor_handle, // Link type matches what we are searching for? auto io_link_type = translated_link_type(link_type); - auto io_link_type_bck(io_link_type); auto num_hops = uint64_t(0); if (auto api_status = amdsmi_topo_get_link_type(processor_handle, device_list[device_idx], &num_hops, &io_link_type); (api_status != amdsmi_status_t::AMDSMI_STATUS_SUCCESS) || (translated_io_link_type(io_link_type) != link_type)) { @@ -2846,7 +2848,7 @@ amdsmi_get_link_topology_nearest(amdsmi_processor_handle processor_handle, * Note: The link topology table is sorted by the number of hops and link weight. */ topology_nearest_info->processor_list[AMDSMI_MAX_DEVICES] = {nullptr}; - topology_nearest_info->count = link_topology_order.size(); + topology_nearest_info->count = static_cast(link_topology_order.size()); auto topology_nearest_counter = uint32_t(0); while (!link_topology_order.empty()) { auto link_info = link_topology_order.top(); @@ -3952,13 +3954,15 @@ amdsmi_status_t amdsmi_get_cpu_handles(uint32_t *cpu_count, } // Get the cpu count - *cpu_count = cpu_handles.size(); - if (processor_handles == nullptr) + *cpu_count = static_cast(cpu_handles.size()); + if (processor_handles == nullptr) { return AMDSMI_STATUS_SUCCESS; + } // Copy the cpu socket handles - for (uint32_t i = 0; i < *cpu_count; i++) + for (uint32_t i = 0; i < *cpu_count; i++) { processor_handles[i] = reinterpret_cast(cpu_handles[i]); + } return status; } @@ -4001,28 +4005,32 @@ amdsmi_status_t amdsmi_get_cpucore_handles(uint32_t *cores_count, // Get the coress for each socket status = amdsmi_get_processor_handles_by_type(sockets[index], processor_type, &plist[0], &cores_per_soc); - if (status != AMDSMI_STATUS_SUCCESS) + if (status != AMDSMI_STATUS_SUCCESS) { return status; + } core_handles.insert(core_handles.end(), plist.begin(), plist.end()); } // Get the cores count - *cores_count = core_handles.size(); - if (processor_handles == nullptr) + *cores_count = static_cast(core_handles.size()); + if (processor_handles == nullptr) { return AMDSMI_STATUS_SUCCESS; + } // Copy the core handles - for (uint32_t i = 0; i < *cores_count; i++) + for (uint32_t i = 0; i < *cores_count; i++) { processor_handles[i] = reinterpret_cast(core_handles[i]); + } return status; } amdsmi_status_t amdsmi_get_esmi_err_msg(amdsmi_status_t status, const char **status_string) { - for (auto& iter : amd::smi::esmi_status_map) { - if (iter.first == status) { + for (const auto& iter : amd::smi::esmi_status_map) { + const amdsmi_status_t _status = status; + if (static_cast(iter.first) == static_cast(_status)) { *status_string = esmi_get_err_msg(static_cast(iter.first)); return iter.second; } diff --git a/src/amd_smi/amd_smi_drm.cc b/src/amd_smi/amd_smi_drm.cc index 41606dfd40..55f0ffb010 100644 --- a/src/amd_smi/amd_smi_drm.cc +++ b/src/amd_smi/amd_smi_drm.cc @@ -41,6 +41,8 @@ namespace smi { std::string AMDSmiDrm::find_file_in_folder(const std::string& folder, const std::string& regex) { std::string file_name; + // TODO: The closedir function has some non-standard attributes that are being ignored here + // which is causing a warning to be thrown using dir_ptr = std::unique_ptr; struct dirent *dir = nullptr; @@ -64,7 +66,6 @@ amdsmi_status_t AMDSmiDrm::init() { // using drm_device_ptr = std::unique_ptr(drmDevicePtr, // decltype(&drmFreeDevice)); - struct dirent *dir = nullptr; int fd = -1; @@ -162,7 +163,7 @@ amdsmi_status_t AMDSmiDrm::init() { << "bdf_rocm | Received bdf: " << "\nWhole BDF: " << amd::smi::print_unsigned_hex_and_int(bdf_rocm) << "\nDomain = " - << amd::smi::print_unsigned_hex_and_int((bdf_rocm & 0xFFFFFFFF00000000) >> 32) + << amd::smi::print_unsigned_hex_and_int((bdf_rocm & static_cast(0xFFFFFFFF00000000)) >> 32) << "; \nBus# = " << amd::smi::print_unsigned_hex_and_int((bdf_rocm & 0xFF00) >> 8) << "; \nDevice# = "<< amd::smi::print_unsigned_hex_and_int((bdf_rocm & 0xF8) >> 3) << "; \nFunction# = " << amd::smi::print_unsigned_hex_and_int((bdf_rocm & 0x7)); @@ -170,6 +171,8 @@ amdsmi_status_t AMDSmiDrm::init() { bdf.function_number = ((bdf_rocm & 0x7)); bdf.device_number = ((bdf_rocm & 0xF8) >> 3); bdf.bus_number = ((bdf_rocm & 0xFF00) >> 8); + // TODO: This is throwing a compiler warning since bdf.domain_number is part of a struct + // and is 48 bits long and throws a conversion warning bdf.domain_number = ((bdf_rocm & 0xFFFFFFFF00000000) >> 32); ss << __PRETTY_FUNCTION__ << " | " << "Received bdf: Domain = " << bdf.domain_number << "; Bus# = " << bdf.bus_number << "; Device# = "<< bdf.device_number diff --git a/src/amd_smi/amd_smi_system.cc b/src/amd_smi/amd_smi_system.cc index 435413dc0b..ea5172ec86 100644 --- a/src/amd_smi/amd_smi_system.cc +++ b/src/amd_smi/amd_smi_system.cc @@ -229,11 +229,15 @@ amdsmi_status_t AMDSmiSystem::get_gpu_socket_id(uint32_t index, */ uint64_t domain = (bdfid >> 32) & 0xffffffff; + /* May need later // may need to identify with partition_id in the future as well... TBD uint64_t partition_id = (bdfid >> 28) & 0xf; + */ uint64_t bus = (bdfid >> 8) & 0xff; uint64_t device_id = (bdfid >> 3) & 0x1f; + /* May need later uint64_t function = bdfid & 0x7; + */ // The BD part of the BDF is used as the socket id as it // represents a physical device. diff --git a/src/amd_smi/amd_smi_utils.cc b/src/amd_smi/amd_smi_utils.cc index 564923029c..b8a7b34601 100644 --- a/src/amd_smi/amd_smi_utils.cc +++ b/src/amd_smi/amd_smi_utils.cc @@ -190,12 +190,11 @@ amdsmi_status_t smi_amdgpu_get_board_info(amd::smi::AMDSmiGPUDevice* device, amd std::string manufacturer_name_path = "/sys/class/drm/" + device->get_gpu_path() + std::string("/device/manufacturer"); std::string product_name_path = "/sys/class/drm/" + device->get_gpu_path() + std::string("/device/product_name"); - openFileAndModifyBuffer(model_number_path, info->model_number, AMDSMI_256_LENGTH); - openFileAndModifyBuffer(product_serial_path, info->product_serial, AMDSMI_NORMAL_STRING_LENGTH); - openFileAndModifyBuffer(fru_id_path, info->fru_id, AMDSMI_NORMAL_STRING_LENGTH); - openFileAndModifyBuffer(manufacturer_name_path, info->manufacturer_name, - AMDSMI_MAX_STRING_LENGTH); - openFileAndModifyBuffer(product_name_path, info->product_name, AMDSMI_256_LENGTH); + openFileAndModifyBuffer(model_number_path, info->model_number, AMDSMI_MAX_STRING_LENGTH); + openFileAndModifyBuffer(product_serial_path, info->product_serial, AMDSMI_MAX_STRING_LENGTH); + openFileAndModifyBuffer(fru_id_path, info->fru_id, AMDSMI_MAX_STRING_LENGTH); + openFileAndModifyBuffer(manufacturer_name_path, info->manufacturer_name, AMDSMI_MAX_STRING_LENGTH); + openFileAndModifyBuffer(product_name_path, info->product_name, AMDSMI_MAX_STRING_LENGTH); std::ostringstream ss; ss << __PRETTY_FUNCTION__ << "[Before correction] " @@ -276,6 +275,12 @@ amdsmi_status_t smi_amdgpu_get_ranges(amd::smi::AMDSmiGPUDevice* device, amdsmi_ case AMDSMI_CLK_TYPE_DCLK1: fullpath += "/pp_dpm_dclk1"; break; + case AMDSMI_CLK_TYPE_SOC: + fullpath += "/pp_dpm_socclk"; + break; + case AMDSMI_CLK_TYPE_DF: + fullpath += "/pp_dpm_fclk"; + break; default: return AMDSMI_STATUS_INVAL; } @@ -522,7 +527,7 @@ amdsmi_status_t smi_amdgpu_get_driver_version(amd::smi::AMDSmiGPUDevice* device, fclose(fp); if (length) { - *length = version[len-1] == '\n' ? len - 1 : len; + *length = version[len-1] == '\n' ? static_cast(len - 1) : static_cast(len); } version[len-1] = version[len-1] == '\n' ? '\0' : version[len-1]; } @@ -584,6 +589,9 @@ amdsmi_status_t smi_amdgpu_get_market_name_from_dev_id(uint32_t device_id, char case 0x74b6: strcpy(market_name, "MI308X"); break; + case 0x74a5: + strcpy(market_name, "AMD Instinct MI325X"); + break; case 0x74a9: case 0x74bd: strcpy(market_name, "AMD Instinct MI300X HF"); @@ -639,6 +647,7 @@ std::string smi_amdgpu_split_string(std::string str, char delim) { tokens.push_back(token); return token; // return 1st match } + return ""; } // wrapper to return string expression of a rsmi_status_t return diff --git a/src/amd_smi/fdinfo.cc b/src/amd_smi/fdinfo.cc index df3a068817..235194e852 100644 --- a/src/amd_smi/fdinfo.cc +++ b/src/amd_smi/fdinfo.cc @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -75,11 +76,11 @@ amdsmi_status_t gpuvsmi_get_pids(const amdsmi_bdf_t &bdf, std::vector struct dirent *dir; /* 0000:00:00.0 */ - snprintf(bdf_str, 13, "%04x:%02x:%02x.%d", - bdf.domain_number & 0xffff, - bdf.bus_number & 0xff, - bdf.device_number & 0x1f, - bdf.function_number & 0x7); + snprintf(bdf_str, 13, "%04" PRIx32 ":%02" PRIx32 ":%02" PRIx32 ".%" PRIu32, + static_cast(bdf.domain_number & 0xffff), + static_cast(bdf.bus_number & 0xff), + static_cast(bdf.device_number & 0x1f), + static_cast(bdf.function_number & 0x7)); d = opendir("/proc"); if (!d) @@ -124,12 +125,11 @@ amdsmi_status_t gpuvsmi_get_pid_info(const amdsmi_bdf_t &bdf, long int pid, struct dirent *dir; /* 0000:00:00.0 */ - snprintf(bdf_str, 13, "%04x:%02x:%02x.%d", - bdf.domain_number & 0xffff, - bdf.bus_number & 0xff, - bdf.device_number & 0x1f, - bdf.function_number & 0x7); - + snprintf(bdf_str, 13, "%04" PRIx32 ":%02" PRIx32 ":%02" PRIx32 ".%" PRIu32, + static_cast(bdf.domain_number & 0xffff), + static_cast(bdf.bus_number & 0xff), + static_cast(bdf.device_number & 0x1f), + static_cast(bdf.function_number & 0x7)); std::string path = "/proc/" + std::to_string(pid) + "/fdinfo/"; std::string name_path = "/proc/" + std::to_string(pid) + "/comm"; @@ -158,7 +158,7 @@ amdsmi_status_t gpuvsmi_get_pid_info(const amdsmi_bdf_t &bdf, long int pid, char fd_bdf_str[13]; /* Only check against fdinfo files that contain a bdf */ - if (sscanf(bdfline.c_str(), "drm-pdev: %s", &fd_bdf_str) != 1) + if (sscanf(bdfline.c_str(), "drm-pdev: %s", &fd_bdf_str[0]) != 1) continue; /* Populate amdsmi_proc_info_t struct only if the bdf in diff --git a/tests/amd_smi_test/functional/api_support_read.cc b/tests/amd_smi_test/functional/api_support_read.cc index 4f58f7b7a0..6be61a276b 100644 --- a/tests/amd_smi_test/functional/api_support_read.cc +++ b/tests/amd_smi_test/functional/api_support_read.cc @@ -63,8 +63,6 @@ void TestAPISupportRead::Close() { } void TestAPISupportRead::Run(void) { - amdsmi_status_t err; - TestBase::Run(); if (setup_failed_) { IF_VERB(STANDARD) { diff --git a/tests/amd_smi_test/functional/fan_read.cc b/tests/amd_smi_test/functional/fan_read.cc index 0f923eed94..0a351cb826 100644 --- a/tests/amd_smi_test/functional/fan_read.cc +++ b/tests/amd_smi_test/functional/fan_read.cc @@ -100,7 +100,7 @@ void TestFanRead::Run(void) { err = amdsmi_get_gpu_fan_speed_max(processor_handles_[i], 0, &val_ui64); CHK_ERR_ASRT(err) IF_VERB(STANDARD) { - std::cout << val_i64/static_cast(val_ui64)*100; + std::cout << static_cast(val_i64)/static_cast(val_ui64)*100; std::cout << "% ("<< val_i64 << "/" << val_ui64 << ")" << std::endl; } // Verify api support checking functionality is working diff --git a/tests/amd_smi_test/functional/fan_read_write.cc b/tests/amd_smi_test/functional/fan_read_write.cc index 32b3fb2802..ee3a1c5a21 100644 --- a/tests/amd_smi_test/functional/fan_read_write.cc +++ b/tests/amd_smi_test/functional/fan_read_write.cc @@ -100,7 +100,7 @@ void TestFanReadWrite::Run(void) { ret = amdsmi_get_gpu_fan_speed_max(processor_handles_[dv_ind], 0, &max_speed); CHK_ERR_ASRT(ret) - new_speed = 1.1 * orig_speed; + new_speed = static_cast(1.1F * static_cast(orig_speed)); if (new_speed > static_cast(max_speed)) { std::cout << @@ -135,8 +135,9 @@ void TestFanReadWrite::Run(void) { // cur_speed < 1.1 * new_speed) || // cur_speed > 0.95 * AMDSMI_MAX_FAN_SPEED); IF_VERB(STANDARD) { - if (!((cur_speed > 0.95 * new_speed && cur_speed < 1.1 * new_speed) || - (cur_speed > 0.95 * AMDSMI_MAX_FAN_SPEED))) { + if (!((cur_speed > static_cast(0.95 * static_cast(new_speed)) && + cur_speed < static_cast(1.10 * static_cast(new_speed))) || + (cur_speed > static_cast(0.95 * AMDSMI_MAX_FAN_SPEED)))) { std::cout << "WARNING: Fan speed is not within the expected range!" << std::endl; } diff --git a/tests/amd_smi_test/functional/gpu_busy_read.cc b/tests/amd_smi_test/functional/gpu_busy_read.cc index 5e290374da..56f92a28c6 100644 --- a/tests/amd_smi_test/functional/gpu_busy_read.cc +++ b/tests/amd_smi_test/functional/gpu_busy_read.cc @@ -63,9 +63,6 @@ void TestGPUBusyRead::Close() { void TestGPUBusyRead::Run(void) { - amdsmi_status_t err; - uint32_t val_ui32; - TestBase::Run(); if (setup_failed_) { std::cout << "** SetUp Failed for this test. Skipping.**" << std::endl; diff --git a/tests/amd_smi_test/functional/hw_topology_read.cc b/tests/amd_smi_test/functional/hw_topology_read.cc index 1079b31be9..390dbec0ce 100644 --- a/tests/amd_smi_test/functional/hw_topology_read.cc +++ b/tests/amd_smi_test/functional/hw_topology_read.cc @@ -20,6 +20,7 @@ * THE SOFTWARE. */ +#include #include #include @@ -477,8 +478,11 @@ void TestHWTopologyRead::Run(void) { continue; } - printf("\tGPU BDF %04lx:%02x:%02x.%d\n", bdf.domain_number, - bdf.bus_number, bdf.device_number, bdf.function_number); + printf("\tGPU BDF %04" PRIx64 ":%02" PRIx32 ":%02" PRIx32 ".%" PRIu32 "\n", + static_cast(bdf.domain_number), + static_cast(bdf.bus_number), + static_cast(bdf.device_number), + static_cast(bdf.function_number)); } } else { diff --git a/tests/amd_smi_test/functional/id_info_read.cc b/tests/amd_smi_test/functional/id_info_read.cc index e85f57d102..91649cf97b 100644 --- a/tests/amd_smi_test/functional/id_info_read.cc +++ b/tests/amd_smi_test/functional/id_info_read.cc @@ -67,7 +67,6 @@ void TestIdInfoRead::Run(void) { amdsmi_status_t err; uint16_t id; uint64_t val_ui64; - uint32_t drm_render_minor; char buffer[kBufferLen]; diff --git a/tests/amd_smi_test/functional/init_shutdown_refcount.cc b/tests/amd_smi_test/functional/init_shutdown_refcount.cc index b9fb9eef2a..55f7733278 100644 --- a/tests/amd_smi_test/functional/init_shutdown_refcount.cc +++ b/tests/amd_smi_test/functional/init_shutdown_refcount.cc @@ -38,7 +38,7 @@ rsmi_test_refcount(uint64_t refcnt_type); static void rand_sleep_mod(int msec) { assert(msec > 10); - unsigned int seed = time(NULL); + uint64_t seed = static_cast(time(NULL)); std::mt19937_64 eng{seed}; std::uniform_int_distribution<> dist{10, msec}; std::this_thread::sleep_for(std::chrono::milliseconds{dist(eng)}); diff --git a/tests/amd_smi_test/functional/mem_util_read.cc b/tests/amd_smi_test/functional/mem_util_read.cc index ce327b5341..ba10947138 100644 --- a/tests/amd_smi_test/functional/mem_util_read.cc +++ b/tests/amd_smi_test/functional/mem_util_read.cc @@ -117,7 +117,7 @@ void TestMemUtilRead::Run(void) { std::cout << "\t**" << kDevMemoryTypeNameMap.at(static_cast(mem_type)) << " Calculated Utilization: " << - (static_cast(usage)*100)/total << "% ("<< usage << + (static_cast(usage)*100)/static_cast(total) << "% ("<< usage << "/" << total << ")" << std::endl; } } diff --git a/tests/amd_smi_test/functional/metrics_counter_read.cc b/tests/amd_smi_test/functional/metrics_counter_read.cc index f6cd1ff95e..b2e9c91b9e 100644 --- a/tests/amd_smi_test/functional/metrics_counter_read.cc +++ b/tests/amd_smi_test/functional/metrics_counter_read.cc @@ -99,7 +99,7 @@ void TestMetricsCounterRead::Run(void) { std::cout << std::dec << "energy_accumulator counter=" << energy_accumulator << '\n'; std::cout << "energy_accumulator in uJ=" - << (double)(energy_accumulator * counter_resolution) << '\n'; + << static_cast((static_cast(energy_accumulator) * counter_resolution)) << '\n'; std::cout << std::dec << "timestamp=" << timestamp << '\n'; } diff --git a/tests/amd_smi_test/functional/mutual_exclusion.cc b/tests/amd_smi_test/functional/mutual_exclusion.cc index ecff87461d..51ce7648ab 100644 --- a/tests/amd_smi_test/functional/mutual_exclusion.cc +++ b/tests/amd_smi_test/functional/mutual_exclusion.cc @@ -155,7 +155,6 @@ void TestMutualExclusion::Run(void) { // Set dummy values should to working, deterministic values. uint16_t dmy_ui16 = 0; uint32_t dmy_ui32 = 1; - uint32_t dmy_i32 = 0; uint64_t dmy_ui64 = 0; int64_t dmy_i64 = 0; char dmy_str[10]; diff --git a/tests/amd_smi_test/functional/perf_cntr_read_write.cc b/tests/amd_smi_test/functional/perf_cntr_read_write.cc index da65c75e0c..5d96c45252 100644 --- a/tests/amd_smi_test/functional/perf_cntr_read_write.cc +++ b/tests/amd_smi_test/functional/perf_cntr_read_write.cc @@ -121,7 +121,7 @@ void TestPerfCntrReadWrite::CountEvents(amdsmi_processor_handle dv_ind, std::cout << "\t\t\tTime Enabled (nS): " << val->time_enabled << std::endl; std::cout << "\t\t\tTime Running (nS): " << val->time_running << std::endl; std::cout << "\t\t\tEvents/Second Running: " << - val->value/static_cast(val->time_running) << std::endl; + static_cast(val->value)/static_cast(val->time_running) << std::endl; } ret = amdsmi_gpu_destroy_counter(evt_handle); CHK_ERR_ASRT(ret) @@ -158,14 +158,14 @@ TestPerfCntrReadWrite::testEventsIndividually(amdsmi_processor_handle dv_ind) { CountEvents(dv_ind, evt, &val, 1); double coll_time_sec = static_cast(val.time_running)/kGig; - throughput = (val.value * 32)/coll_time_sec; + throughput = static_cast(static_cast((val.value * 32L))/coll_time_sec); std::cout << "\t\t\tCollected events for " << coll_time_sec << " seconds" << std::endl; std::cout << "\t\t\tEvents collected: " << val.value << std::endl; std::cout << "\t\t\tXGMI throughput: " << throughput << " bytes/second" << std::endl; std::cout << "\t\t\tXGMI Channel Utilization: " << - 100*throughput/static_cast(kVg20Level1Bandwidth*kGigByte) << + static_cast(100*throughput)/static_cast(kVg20Level1Bandwidth*kGigByte) << "%" << std::endl; std::cout << "\t\t\t****" << std::endl; } diff --git a/tests/amd_smi_test/functional/power_read.cc b/tests/amd_smi_test/functional/power_read.cc index 345b17fb8a..e898aca165 100644 --- a/tests/amd_smi_test/functional/power_read.cc +++ b/tests/amd_smi_test/functional/power_read.cc @@ -64,8 +64,6 @@ void TestPowerRead::Close() { void TestPowerRead::Run(void) { amdsmi_status_t err; - uint64_t val_ui64, val2_ui64; - amdsmi_power_type_t type = AMDSMI_INVALID_POWER; TestBase::Run(); if (setup_failed_) { diff --git a/tests/amd_smi_test/functional/sys_info_read.cc b/tests/amd_smi_test/functional/sys_info_read.cc index 6466af4a90..b6e5cbd9ba 100644 --- a/tests/amd_smi_test/functional/sys_info_read.cc +++ b/tests/amd_smi_test/functional/sys_info_read.cc @@ -69,9 +69,7 @@ void TestSysInfoRead::Close() { void TestSysInfoRead::Run(void) { amdsmi_status_t err; uint64_t val_ui64; - uint32_t val_ui32; int32_t val_i32; - char buffer[80]; amdsmi_version_t ver = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, nullptr}; TestBase::Run(); diff --git a/tests/amd_smi_test/functional/xgmi_read_write.cc b/tests/amd_smi_test/functional/xgmi_read_write.cc index d1017c7aae..7efdf57489 100644 --- a/tests/amd_smi_test/functional/xgmi_read_write.cc +++ b/tests/amd_smi_test/functional/xgmi_read_write.cc @@ -65,7 +65,6 @@ void TestXGMIReadWrite::Run(void) { GTEST_SKIP_("Temporarily disabled"); amdsmi_status_t err; amdsmi_xgmi_status_t err_stat; - uint64_t hive_id; TestBase::Run(); if (setup_failed_) {