Commit 1473d3b8 authored by Michael Piszczek's avatar Michael Piszczek Committed by Tomasz Zawadzki
Browse files

env_dpdk: fix check for AMD iommu



Update code for read the virtual address width to use glob to locate the
Intel and AMD iommu capability registers. This code should work for all
AMD numa configurations.

Fixes issue 2730

Signed-off-by: default avatarMichael Piszczek <mpiszczek@ddn.com>
Change-Id: Ibf5789087b7e372d892b53101e4c0231809053f0
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14961


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarPaul Luse <paul.e.luse@intel.com>
Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Community-CI: Mellanox Build Bot
parent 0d0de8e7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ extern "C" {
#include <arpa/inet.h>
#include <dirent.h>
#include <fcntl.h>
#include <glob.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <poll.h>
+29 −82
Original line number Diff line number Diff line
@@ -157,96 +157,43 @@ push_arg(char *args[], int *argcount, char *arg)
#define RD_AMD_CAP_VASIZE_SHIFT 15
#define RD_AMD_CAP_VASIZE_MASK (0x7F << RD_AMD_CAP_VASIZE_SHIFT)

static int
get_amd_iommu_width(void)
{
	FILE *file;
	char buf[64];
	char *end;
	long long int amd_cap;

	file = fopen("/sys/class/iommu/ivhd2/amd-iommu/cap", "r");
	if (file == NULL) {
		return 0;
	}

	if (fgets(buf, sizeof(buf), file) == NULL) {
		fclose(file);
		return 0;
	}

	amd_cap = strtoll(buf, &end, 16);
	if (amd_cap == LLONG_MIN || amd_cap == LLONG_MAX) {
		fclose(file);
		return 0;
	}

	fclose(file);
	return (amd_cap & RD_AMD_CAP_VASIZE_MASK) >> RD_AMD_CAP_VASIZE_SHIFT;
}

static int
get_iommu_width(void)
{
	DIR *dir;
	FILE *file;
	struct dirent *entry;
	char mgaw_path[64];
	char buf[64];
	char *end;
	long long int val;
	int width, tmp;
	struct stat s;

	if (stat("/sys/class/iommu/ivhd2/amd-iommu", &s) == 0) {
		return get_amd_iommu_width();
	}

	dir = opendir("/sys/devices/virtual/iommu/");
	if (dir == NULL) {
		return -EINVAL;
	}
	int width = 0;
	glob_t glob_results = {};

	width = 0;
	/* Break * and / into separate strings to appease check_format.sh comment style check. */
	glob("/sys/devices/virtual/iommu/dmar*" "/intel-iommu/cap", 0, NULL, &glob_results);
	glob("/sys/class/iommu/ivhd*" "/amd-iommu/cap", GLOB_APPEND, NULL, &glob_results);

	while ((entry = readdir(dir)) != NULL) {
		/* Find directories named "dmar0", "dmar1", etc */
		if (strncmp(entry->d_name, "dmar", sizeof("dmar") - 1) != 0) {
			continue;
		}
	for (size_t i = 0; i < glob_results.gl_pathc; i++) {
		const char *filename = glob_results.gl_pathv[0];
		FILE *file = fopen(filename, "r");
		uint64_t cap_reg = 0;

		tmp = snprintf(mgaw_path, sizeof(mgaw_path), "/sys/devices/virtual/iommu/%s/intel-iommu/cap",
			       entry->d_name);
		if ((unsigned)tmp >= sizeof(mgaw_path)) {
			continue;
		}
		if (file != NULL && fscanf(file, "%" PRIx64, &cap_reg) == 1) {
			if (strstr(filename, "intel-iommu") != NULL) {
				/* We have an Intel IOMMU */
				int mgaw = ((cap_reg & VTD_CAP_MGAW_MASK) >> VTD_CAP_MGAW_SHIFT) + 1;

		file = fopen(mgaw_path, "r");
		if (file == NULL) {
			continue;
				if (width == 0 || (mgaw > 0 && mgaw < width)) {
					width = mgaw;
				}
			} else if (strstr(filename, "amd-iommu") != NULL) {
				/* We have an AMD IOMMU */
				int mgaw = ((cap_reg & RD_AMD_CAP_VASIZE_MASK) >> RD_AMD_CAP_VASIZE_SHIFT) + 1;

		if (fgets(buf, sizeof(buf), file) == NULL) {
			fclose(file);
			continue;
				if (width == 0 || (mgaw > 0 && mgaw < width)) {
					width = mgaw;
				}

		val = strtoll(buf, &end, 16);
		if (val == LLONG_MIN || val == LLONG_MAX) {
			fclose(file);
			continue;
			}

		tmp = ((val & VTD_CAP_MGAW_MASK) >> VTD_CAP_MGAW_SHIFT) + 1;
		if (width == 0 || tmp < width) {
			width = tmp;
		}

		fclose(file);
	}

	closedir(dir);

	globfree(&glob_results);
	return width;
}