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: Michael Piszczek <mpiszczek@ddn.com>
Change-Id: Ibf5789087b7e372d892b53101e4c0231809053f0
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14961
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Community-CI: Mellanox Build Bot
This commit is contained in:
Michael Piszczek 2022-10-13 19:26:06 +00:00 committed by Tomasz Zawadzki
parent 0d0de8e7d9
commit 1473d3b8c2
2 changed files with 25 additions and 77 deletions

View File

@ -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>

View File

@ -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;
int width = 0;
glob_t glob_results = {};
if (stat("/sys/class/iommu/ivhd2/amd-iommu", &s) == 0) {
return get_amd_iommu_width();
}
/* 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);
dir = opendir("/sys/devices/virtual/iommu/");
if (dir == NULL) {
return -EINVAL;
}
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;
width = 0;
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;
while ((entry = readdir(dir)) != NULL) {
/* Find directories named "dmar0", "dmar1", etc */
if (strncmp(entry->d_name, "dmar", sizeof("dmar") - 1) != 0) {
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;
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;
}
file = fopen(mgaw_path, "r");
if (file == NULL) {
continue;
}
if (fgets(buf, sizeof(buf), file) == NULL) {
fclose(file);
continue;
}
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;
if (width == 0 || (mgaw > 0 && mgaw < width)) {
width = mgaw;
}
}
}
fclose(file);
}
closedir(dir);
globfree(&glob_results);
return width;
}