From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 50E3FEE57D1 for ; Wed, 31 Dec 2025 05:55:31 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 68BB910E8D0; Wed, 31 Dec 2025 05:55:30 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="XqQ56y+h"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.12]) by gabe.freedesktop.org (Postfix) with ESMTPS id 8004C10E8D0 for ; Wed, 31 Dec 2025 05:55:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1767160530; x=1798696530; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=cBDEFeh90/r3rIjhemR22+zjC9svL16Muu22M2K+ghY=; b=XqQ56y+ha+GZROPCS9/JX9NLHTwYB3vnkMxdNDMZ17jwoGA/q1gm/7te O/6IoHp1vH1dRGiJh7xkPZnAq8fj6RlWdp6macUtmzF85bxpkJioQss7Z d3ed9OC8MmJI6vN3hOLfezgRj9U3f74w7Q1mOg7WKyWCGV1wjhChO3CTD BW97qlLC+BTl2XXOtLnRS0lSuxAsVLJSTaAcADfE87vI+kiVrWV3Wormo uWjs4HloTuRUU7PvaGlwD9d+iobAPR1L/gl5JRG0AIs3ZddV1MAlMrsF7 JvFqAFXvTz1Sy1ryGXwc0RpFuZlRPBjcDKA5WojVgGaeMrjYUYHYHv52C Q==; X-CSE-ConnectionGUID: AwAKTQzkTc29mhkXVKXd7A== X-CSE-MsgGUID: fdoyQQKHSTK+mIVVlbbJLg== X-IronPort-AV: E=McAfee;i="6800,10657,11657"; a="72589999" X-IronPort-AV: E=Sophos;i="6.21,191,1763452800"; d="scan'208";a="72589999" Received: from orviesa009.jf.intel.com ([10.64.159.149]) by fmvoesa106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Dec 2025 21:55:29 -0800 X-CSE-ConnectionGUID: 9JHHOV9DS2CD7zs2UzQJWg== X-CSE-MsgGUID: obCtk9gqSaG9Hg+F0kes7Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,191,1763452800"; d="scan'208";a="201119703" Received: from dut6304bmgfrd.fm.intel.com ([10.36.21.42]) by orviesa009.jf.intel.com with ESMTP; 30 Dec 2025 21:55:29 -0800 From: Xin Wang To: igt-dev@lists.freedesktop.org Cc: alex.zuo@intel.com, shuicheng.lin@intel.com, stuart.summers@intel.com, kamil.konieczny@intel.com, matthew.d.roper@intel.com, ravi.kumar.vodapalli@intel.com, zbigniew.kempczynski@intel.com, Xin Wang , Matthew Auld Subject: [PATCH v9 1/5] lib/intel_pat: add pat_sw_config debugfs parser Date: Wed, 31 Dec 2025 05:55:21 +0000 Message-ID: <20251231055525.51524-2-x.wang@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251231055525.51524-1-x.wang@intel.com> References: <20251231055525.51524-1-x.wang@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: igt-dev@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development mailing list for IGT GPU Tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: igt-dev-bounces@lists.freedesktop.org Sender: "igt-dev" Add xe_get_pat_sw_config() to parse the Xe PAT software configuration from debugfs (gt0/pat_sw_config). This is intended for test-only use to validate the kernel-exposed PAT layout against IGT's predefined UC/WT/WB/UC_COMP mapping. The intel_get_pat_idx_*() helpers continue to use a predefined per-devid mapping, keeping them usable from unprivileged users. This avoids introducing a debugfs dependency in the common library path while still allowing tests to detect PAT table drift as new platforms are added. V2: (Kamil) - Show a detailed skip info when opening the debugfs file fails. V3: - Save the Xe PAT software configuration into the xe_dev structure to prevent scenarios where certain test cases drop root privileges after execution begins, which could block access to debugfs. V4: - Cache the parsed PAT table the first time we read pat_sw_config and reuse it for subsequent calls. This avoids repeated debugfs opens (and failures) in tests that drop root between steps, while still returning the correct PAT layout. V5: - Make PAT debugfs parsing lazy: avoid requiring debugfs from xe_device_get(), so tests that don't need PAT won't be skipped. - If PAT info isn't available at device init, keep pat_sw_config empty and only require debugfs when PAT indices are requested. - Add xe_get_pat_entries() helper to expose the parsed PAT entry table. V6: - code optimization V7: - Keep intel_get_pat_*() usable for unprivileged users by switching back to the predefined per-devid UC/WT/WB/UC_COMP mapping (no debugfs required). - Stop reading pat_sw_config from the common device setup path: remove the PAT debugfs fetch from xe_device_get() (and drop the cached field in the xe device struct), avoiding a global debugfs dependency in lib code paths. - Treat PAT parsing as test-only plumbing: make xe_get_pat_sw_config() explicitly root-gated. V8:(Matt Roper) - Return the correct error code when reading pat_sw_config fails. CC: Shuicheng Lin CC: Kamil Konieczny CC: Matt Roper CC: Matthew Auld CC: Zbigniew Kempczyński Signed-off-by: Xin Wang --- lib/intel_pat.c | 94 ++++++++++++++++++++++++++++++++++++++++++++----- lib/intel_pat.h | 20 +++++++++++ 2 files changed, 106 insertions(+), 8 deletions(-) diff --git a/lib/intel_pat.c b/lib/intel_pat.c index e3588110a..127f2160a 100644 --- a/lib/intel_pat.c +++ b/lib/intel_pat.c @@ -3,17 +3,95 @@ * Copyright © 2023 Intel Corporation */ +#include "igt.h" #include "intel_pat.h" -#include "igt.h" +/** + * xe_get_pat_sw_config - Helper to read PAT (Page Attribute Table) software configuration + * from debugfs + * + * @drm_fd: DRM device fd to use with igt_debugfs_open + * @xe_pat_cache: Pointer to a struct that will receive the parsed PAT configuration + * + * Returns: The number of PAT entries successfully read on success, or a negative error + * code on failure + */ +int32_t xe_get_pat_sw_config(int drm_fd, struct intel_pat_cache *xe_pat_cache) +{ + char *line = NULL; + size_t line_len = 0; + ssize_t nread; + int32_t parsed = 0; + int dbgfs_fd; + FILE *dbgfs_file = NULL; + + dbgfs_fd = igt_debugfs_open(drm_fd, "gt0/pat_sw_config", O_RDONLY); + if (dbgfs_fd < 0) + return dbgfs_fd; + dbgfs_file = fdopen(dbgfs_fd, "r"); + if (!dbgfs_file) { + close(dbgfs_fd); + return -errno; + } -struct intel_pat_cache { - uint8_t uc; /* UC + COH_NONE */ - uint8_t wt; /* WT + COH_NONE */ - uint8_t wb; /* WB + COH_AT_LEAST_1WAY */ - uint8_t uc_comp; /* UC + COH_NONE + COMPRESSION, XE2 and later*/ - uint8_t max_index; -}; + memset(xe_pat_cache, 0, sizeof(*xe_pat_cache)); + while ((nread = getline(&line, &line_len, dbgfs_file)) != -1) { + uint32_t value = 0; + char *p = NULL; + + /* Expect patterns like: PAT[ 0] = [ 0, 0, 0, 0, 0 ] ( 0x0) */ + if (strncmp(line, "PAT[", 4) == 0) { + bool is_reserved; + p = strstr(line, "("); + if (p && sscanf(p, "(%x", &value) == 1) { + if (parsed < XE_PAT_MAX_ENTRIES) { + is_reserved = strchr(line, '*') != NULL; + xe_pat_cache->entries[parsed].pat = value; + xe_pat_cache->entries[parsed].rsvd = is_reserved; + xe_pat_cache->max_index = parsed; + parsed++; + + igt_debug("Parsed PAT entry %d: 0x%08x%s\n", + parsed - 1, value, + is_reserved ? " (reserved)" : ""); + } else { + igt_warn("Too many PAT entries, line ignored: %s\n", line); + } + } else { + igt_warn("Failed to parse PAT entry line: %s\n", line); + } + } else if (strncmp(line, "PAT_MODE", 8) == 0) { + p = strstr(line, "("); + if (p && sscanf(p, "(%x", &value) == 1) + xe_pat_cache->pat_mode = value; + } else if (strncmp(line, "PAT_ATS", 7) == 0) { + p = strstr(line, "("); + if (p && sscanf(p, "(%x", &value) == 1) + xe_pat_cache->pat_ats = value; + } else if (strncmp(line, "IDX[XE_CACHE_NONE]", 18) == 0) { + p = strstr(line, "="); + if (p && sscanf(p, "= %d", &value) == 1) + xe_pat_cache->uc = value; + } else if (strncmp(line, "IDX[XE_CACHE_WT]", 16) == 0) { + p = strstr(line, "="); + if (p && sscanf(p, "= %d", &value) == 1) + xe_pat_cache->wt = value; + } else if (strncmp(line, "IDX[XE_CACHE_WB]", 16) == 0) { + p = strstr(line, "="); + if (p && sscanf(p, "= %d", &value) == 1) + xe_pat_cache->wb = value; + } else if (strncmp(line, "IDX[XE_CACHE_NONE_COMPRESSION]", 28) == 0) { + p = strstr(line, "="); + if (p && sscanf(p, "= %d", &value) == 1) + xe_pat_cache->uc_comp = value; + } + } + + free(line); + fclose(dbgfs_file); + + return parsed; +} static void intel_get_pat_idx(int fd, struct intel_pat_cache *pat) { diff --git a/lib/intel_pat.h b/lib/intel_pat.h index eb48cbc65..e9ade2e2e 100644 --- a/lib/intel_pat.h +++ b/lib/intel_pat.h @@ -6,9 +6,27 @@ #ifndef INTEL_PAT_H #define INTEL_PAT_H +#include #include #define DEFAULT_PAT_INDEX ((uint8_t)-1) /* igt-core can pick 1way or better */ +#define XE_PAT_MAX_ENTRIES 32 + +struct xe_pat_entry { + uint32_t pat; + bool rsvd; +}; + +struct intel_pat_cache { + uint8_t uc; /* UC + COH_NONE */ + uint8_t wt; /* WT + COH_NONE */ + uint8_t wb; /* WB + COH_AT_LEAST_1WAY */ + uint8_t uc_comp; /* UC + COH_NONE + COMPRESSION, XE2 and later*/ + uint8_t max_index; + struct xe_pat_entry entries[XE_PAT_MAX_ENTRIES]; + uint32_t pat_mode; + uint32_t pat_ats; +}; uint8_t intel_get_max_pat_index(int fd); @@ -18,4 +36,6 @@ uint8_t intel_get_pat_idx_wb(int fd); uint8_t intel_get_pat_idx_uc_comp(int fd); +int32_t xe_get_pat_sw_config(int drm_fd, struct intel_pat_cache *xe_pat_cache); + #endif /* INTEL_PAT_H */ -- 2.43.0