Message ID | 20250130213028.3852086-4-vinay.belgaumkar@intel.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | tests/intel/xe_pmu: Add PMU tests | expand |
On 1/30/2025 1:30 PM, Vinay Belgaumkar wrote: > Simple tests for validating the PMU implementation for GT C6 > residencies. > > v2: Rename rc6-residency-* to gt-c6-residency and remove freq tests. > v3: Keep just gt-c6 tests, add frequency tests later. > v4: Review comments (Riana) > v5: Review comments (Lucas) > > Cc: Lucas De Marchi <lucas.demarchi@intel.com> > Cc: Riana Tauro <riana.tauro@intel.com> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> > Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com> > --- > tests/intel/xe_pmu.c | 149 +++++++++++++++++++++++++++++++++++++++++++ > tests/meson.build | 1 + > 2 files changed, 150 insertions(+) > create mode 100644 tests/intel/xe_pmu.c > > diff --git a/tests/intel/xe_pmu.c b/tests/intel/xe_pmu.c > new file mode 100644 > index 000000000..44589cb86 > --- /dev/null > +++ b/tests/intel/xe_pmu.c > @@ -0,0 +1,149 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright © 2025 Intel Corporation > + */ > + > +/** > + * TEST: Test Xe PMU functionality > + * Category: Perf Monitoring Unit > + * Mega feature: Perf Monitoring Unit > + * Sub-category: Telemetry > + * Functionality: Power/Perf > + * Test category: Functional tests > + */ > + > +#include <fcntl.h> > +#include <limits.h> > +#include <time.h> > +#include <errno.h> > +#include <dirent.h> > +#include <string.h> > +#include <sys/time.h> > + > +#include "igt.h" > +#include "igt_device.h" > +#include "igt_power.h" > +#include "igt_sysfs.h" > +#include "igt_perf.h" > + > +#include "lib/igt_syncobj.h" > +#include "xe/xe_ioctl.h" > +#include "xe/xe_gt.h" > +#include "xe/xe_query.h" > +#include "xe/xe_spin.h" > +#include "xe/xe_util.h" > + > +#define SLEEP_DURATION 2 /* in seconds */ > +const double tolerance = 0.1; > +const char *no_debug_data = "\0"; This one got missed. Will remove in the next version after reviews are complete. Thanks, Vinay. > + > +static int open_pmu(int xe, uint64_t config) > +{ > + int fd; > + > + fd = perf_xe_open(xe, config); > + igt_skip_on(fd < 0 && errno == ENODEV); > + igt_assert(fd >= 0); > + > + return fd; > +} > + > +static uint64_t __pmu_read_single(int fd, uint64_t *ts) > +{ > + uint64_t data[2]; > + > + igt_assert_eq(read(fd, data, sizeof(data)), sizeof(data)); > + if (ts) > + *ts = data[1]; > + > + return data[0]; > +} > + > +static unsigned long read_idle_residency(int fd, int gt) > +{ > + unsigned long residency = 0; > + int gt_fd; > + > + gt_fd = xe_sysfs_gt_open(fd, gt); > + igt_assert(gt_fd >= 0); > + igt_assert(igt_sysfs_scanf(gt_fd, "gtidle/idle_residency_ms", "%lu", &residency) == 1); > + close(gt_fd); > + > + return residency; > +} > + > +static u64 get_event_config(int xe, unsigned int gt, char *event) > +{ > + int ret; > + char xe_device[100]; > + u64 pmu_config; > + u32 start, end; > + > + xe_perf_device(xe, xe_device, sizeof(xe_device)); > + ret = perf_event_config(xe_device, event, &pmu_config); > + igt_assert(ret >= 0); > + ret = perf_event_format(xe_device, "gt", &start, &end); > + igt_assert(ret >= 0); > + pmu_config |= (u64) gt << start; > + > + return pmu_config; > +} > + > +/** > + * SUBTEST: gt-c6-idle > + * Description: Basic residency test to validate idle residency > + * measured over a time interval is within the tolerance > + */ > +static void test_gt_c6_idle(int xe, unsigned int gt) > +{ > + int pmu_fd; > + u64 pmu_config; > + char event[100]; > + uint64_t ts[2]; > + unsigned long slept, start, end; > + uint64_t val; > + > + /* Get the PMU config for the gt-c6 event */ > + sprintf(event, "gt-c6-residency"); > + pmu_config = get_event_config(xe, gt, event); > + > + pmu_fd = open_pmu(xe, pmu_config); > + > + igt_require_f(igt_wait(xe_gt_is_in_c6(xe, gt), 1000, 10), "GT %d should be in C6\n", gt); > + > + /* While idle check full RC6. */ > + start = read_idle_residency(xe, gt); > + val = __pmu_read_single(pmu_fd, &ts[0]); > + slept = igt_measured_usleep(SLEEP_DURATION * USEC_PER_SEC) / 1000; > + end = read_idle_residency(xe, gt); > + val = __pmu_read_single(pmu_fd, &ts[1]) - val; > + > + igt_debug("gt%u: slept=%lu, perf=%"PRIu64"\n", > + gt, slept, val); > + > + igt_debug("Start res: %lu, end_res: %lu", start, end); > + > + assert_within_epsilon(val, > + (ts[1] - ts[0])/USEC_PER_SEC, > + tolerance); > + close(pmu_fd); > +} > + > +igt_main > +{ > + int fd, gt; > + > + igt_fixture { > + fd = drm_open_driver(DRIVER_XE); > + igt_require(!IS_PONTEVECCHIO(xe_dev_id(fd))); > + } > + > + igt_describe("Validate PMU gt-c6 residency counters when idle"); > + igt_subtest("gt-c6-idle") > + xe_for_each_gt(fd, gt) > + test_gt_c6_idle(fd, gt); > + > + igt_fixture { > + close(fd); > + } > +} > diff --git a/tests/meson.build b/tests/meson.build > index 33dffad31..d20f50766 100644 > --- a/tests/meson.build > +++ b/tests/meson.build > @@ -309,6 +309,7 @@ intel_xe_progs = [ > 'xe_pat', > 'xe_peer2peer', > 'xe_pm', > + 'xe_pmu', > 'xe_pm_residency', > 'xe_prime_self_import', > 'xe_query',
Hi Vinay On 1/31/2025 3:00 AM, Vinay Belgaumkar wrote: > Simple tests for validating the PMU implementation for GT C6 > residencies. > > v2: Rename rc6-residency-* to gt-c6-residency and remove freq tests. > v3: Keep just gt-c6 tests, add frequency tests later. > v4: Review comments (Riana) > v5: Review comments (Lucas) > > Cc: Lucas De Marchi <lucas.demarchi@intel.com> > Cc: Riana Tauro <riana.tauro@intel.com> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> > Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com> > --- > tests/intel/xe_pmu.c | 149 +++++++++++++++++++++++++++++++++++++++++++ > tests/meson.build | 1 + > 2 files changed, 150 insertions(+) > create mode 100644 tests/intel/xe_pmu.c > > diff --git a/tests/intel/xe_pmu.c b/tests/intel/xe_pmu.c > new file mode 100644 > index 000000000..44589cb86 > --- /dev/null > +++ b/tests/intel/xe_pmu.c > @@ -0,0 +1,149 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright © 2025 Intel Corporation > + */ > + > +/** > + * TEST: Test Xe PMU functionality > + * Category: Perf Monitoring Unit > + * Mega feature: Perf Monitoring Unit > + * Sub-category: Telemetry > + * Functionality: Power/Perf > + * Test category: Functional tests > + */ > + > +#include <fcntl.h> > +#include <limits.h> > +#include <time.h> > +#include <errno.h> > +#include <dirent.h> > +#include <string.h> > +#include <sys/time.h> > + > +#include "igt.h" > +#include "igt_device.h" > +#include "igt_power.h" > +#include "igt_sysfs.h" > +#include "igt_perf.h" > + > +#include "lib/igt_syncobj.h" > +#include "xe/xe_ioctl.h" > +#include "xe/xe_gt.h" > +#include "xe/xe_query.h" > +#include "xe/xe_spin.h" > +#include "xe/xe_util.h" few headers here that are not used > + > +#define SLEEP_DURATION 2 /* in seconds */ > +const double tolerance = 0.1; > +const char *no_debug_data = "\0"; > + > +static int open_pmu(int xe, uint64_t config) > +{ > + int fd; > + > + fd = perf_xe_open(xe, config); > + igt_skip_on(fd < 0 && errno == ENODEV); > + igt_assert(fd >= 0); > + > + return fd; > +} > + > +static uint64_t __pmu_read_single(int fd, uint64_t *ts) > +{ > + uint64_t data[2]; > + > + igt_assert_eq(read(fd, data, sizeof(data)), sizeof(data)); > + if (ts) > + *ts = data[1]; > + > + return data[0]; > +} > + > +static unsigned long read_idle_residency(int fd, int gt) > +{ > + unsigned long residency = 0; > + int gt_fd; > + > + gt_fd = xe_sysfs_gt_open(fd, gt); > + igt_assert(gt_fd >= 0); > + igt_assert(igt_sysfs_scanf(gt_fd, "gtidle/idle_residency_ms", "%lu", &residency) == 1); > + close(gt_fd); > + > + return residency; > +} > + > +static u64 get_event_config(int xe, unsigned int gt, char *event) > +{ > + int ret; > + char xe_device[100]; > + u64 pmu_config; %/u64/uint64_t igt uses uint64_t mostly. To maintain consistency, u32 and u64 in this file should be replaced with uint64_t . With the above comments fixed Reviewed-by: Riana Tauro <riana.tauro@intel.com> > + u32 start, end; > + > + xe_perf_device(xe, xe_device, sizeof(xe_device)); > + ret = perf_event_config(xe_device, event, &pmu_config); > + igt_assert(ret >= 0); > + ret = perf_event_format(xe_device, "gt", &start, &end); > + igt_assert(ret >= 0); > + pmu_config |= (u64) gt << start; > + > + return pmu_config; > +} > + > +/** > + * SUBTEST: gt-c6-idle > + * Description: Basic residency test to validate idle residency > + * measured over a time interval is within the tolerance > + */ > +static void test_gt_c6_idle(int xe, unsigned int gt) > +{ > + int pmu_fd; > + u64 pmu_config; > + char event[100]; > + uint64_t ts[2]; > + unsigned long slept, start, end; > + uint64_t val; > + > + /* Get the PMU config for the gt-c6 event */ > + sprintf(event, "gt-c6-residency"); > + pmu_config = get_event_config(xe, gt, event); > + > + pmu_fd = open_pmu(xe, pmu_config); > + > + igt_require_f(igt_wait(xe_gt_is_in_c6(xe, gt), 1000, 10), "GT %d should be in C6\n", gt); > + > + /* While idle check full RC6. */ > + start = read_idle_residency(xe, gt); > + val = __pmu_read_single(pmu_fd, &ts[0]); > + slept = igt_measured_usleep(SLEEP_DURATION * USEC_PER_SEC) / 1000; > + end = read_idle_residency(xe, gt); > + val = __pmu_read_single(pmu_fd, &ts[1]) - val; > + > + igt_debug("gt%u: slept=%lu, perf=%"PRIu64"\n", > + gt, slept, val); > + > + igt_debug("Start res: %lu, end_res: %lu", start, end); > + > + assert_within_epsilon(val, > + (ts[1] - ts[0])/USEC_PER_SEC, > + tolerance); > + close(pmu_fd); > +} > + > +igt_main > +{ > + int fd, gt; > + > + igt_fixture { > + fd = drm_open_driver(DRIVER_XE); > + igt_require(!IS_PONTEVECCHIO(xe_dev_id(fd))); > + } > + > + igt_describe("Validate PMU gt-c6 residency counters when idle"); > + igt_subtest("gt-c6-idle") > + xe_for_each_gt(fd, gt) > + test_gt_c6_idle(fd, gt); > + > + igt_fixture { > + close(fd); > + } > +} > diff --git a/tests/meson.build b/tests/meson.build > index 33dffad31..d20f50766 100644 > --- a/tests/meson.build > +++ b/tests/meson.build > @@ -309,6 +309,7 @@ intel_xe_progs = [ > 'xe_pat', > 'xe_peer2peer', > 'xe_pm', > + 'xe_pmu', > 'xe_pm_residency', > 'xe_prime_self_import', > 'xe_query',
Hi Vinay, On 2025-01-30 at 13:30:28 -0800, Vinay Belgaumkar wrote: > Simple tests for validating the PMU implementation for GT C6 > residencies. > > v2: Rename rc6-residency-* to gt-c6-residency and remove freq tests. > v3: Keep just gt-c6 tests, add frequency tests later. > v4: Review comments (Riana) > v5: Review comments (Lucas) > > Cc: Lucas De Marchi <lucas.demarchi@intel.com> > Cc: Riana Tauro <riana.tauro@intel.com> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> > Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com> > --- > tests/intel/xe_pmu.c | 149 +++++++++++++++++++++++++++++++++++++++++++ > tests/meson.build | 1 + > 2 files changed, 150 insertions(+) > create mode 100644 tests/intel/xe_pmu.c > > diff --git a/tests/intel/xe_pmu.c b/tests/intel/xe_pmu.c > new file mode 100644 > index 000000000..44589cb86 > --- /dev/null > +++ b/tests/intel/xe_pmu.c > @@ -0,0 +1,149 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright © 2025 Intel Corporation > + */ > + > +/** > + * TEST: Test Xe PMU functionality > + * Category: Perf Monitoring Unit > + * Mega feature: Perf Monitoring Unit > + * Sub-category: Telemetry > + * Functionality: Power/Perf > + * Test category: Functional tests Sort this alphabetically, also add description with PMU deciphered: * Description: Tests Performance Monitoring Unit PMU > + */ > + > +#include <fcntl.h> > +#include <limits.h> > +#include <time.h> > +#include <errno.h> > +#include <dirent.h> > +#include <string.h> > +#include <sys/time.h> Sort these headers. > + > +#include "igt.h" > +#include "igt_device.h" > +#include "igt_power.h" > +#include "igt_sysfs.h" > +#include "igt_perf.h" > + > +#include "lib/igt_syncobj.h" > +#include "xe/xe_ioctl.h" > +#include "xe/xe_gt.h" > +#include "xe/xe_query.h" > +#include "xe/xe_spin.h" > +#include "xe/xe_util.h" > + > +#define SLEEP_DURATION 2 /* in seconds */ > +const double tolerance = 0.1; > +const char *no_debug_data = "\0"; > + > +static int open_pmu(int xe, uint64_t config) > +{ > + int fd; > + > + fd = perf_xe_open(xe, config); > + igt_skip_on(fd < 0 && errno == ENODEV); > + igt_assert(fd >= 0); > + > + return fd; > +} > + > +static uint64_t __pmu_read_single(int fd, uint64_t *ts) > +{ > + uint64_t data[2]; > + > + igt_assert_eq(read(fd, data, sizeof(data)), sizeof(data)); > + if (ts) > + *ts = data[1]; > + > + return data[0]; > +} > + > +static unsigned long read_idle_residency(int fd, int gt) > +{ > + unsigned long residency = 0; > + int gt_fd; > + > + gt_fd = xe_sysfs_gt_open(fd, gt); > + igt_assert(gt_fd >= 0); > + igt_assert(igt_sysfs_scanf(gt_fd, "gtidle/idle_residency_ms", "%lu", &residency) == 1); > + close(gt_fd); > + > + return residency; > +} > + > +static u64 get_event_config(int xe, unsigned int gt, char *event) > +{ > + int ret; > + char xe_device[100]; > + u64 pmu_config; > + u32 start, end; > + > + xe_perf_device(xe, xe_device, sizeof(xe_device)); > + ret = perf_event_config(xe_device, event, &pmu_config); > + igt_assert(ret >= 0); > + ret = perf_event_format(xe_device, "gt", &start, &end); > + igt_assert(ret >= 0); > + pmu_config |= (u64) gt << start; > + > + return pmu_config; > +} > + > +/** > + * SUBTEST: gt-c6-idle > + * Description: Basic residency test to validate idle residency > + * measured over a time interval is within the tolerance > + */ > +static void test_gt_c6_idle(int xe, unsigned int gt) > +{ > + int pmu_fd; > + u64 pmu_config; > + char event[100]; > + uint64_t ts[2]; > + unsigned long slept, start, end; > + uint64_t val; > + > + /* Get the PMU config for the gt-c6 event */ > + sprintf(event, "gt-c6-residency"); > + pmu_config = get_event_config(xe, gt, event); > + > + pmu_fd = open_pmu(xe, pmu_config); > + > + igt_require_f(igt_wait(xe_gt_is_in_c6(xe, gt), 1000, 10), "GT %d should be in C6\n", gt); > + > + /* While idle check full RC6. */ > + start = read_idle_residency(xe, gt); > + val = __pmu_read_single(pmu_fd, &ts[0]); > + slept = igt_measured_usleep(SLEEP_DURATION * USEC_PER_SEC) / 1000; > + end = read_idle_residency(xe, gt); > + val = __pmu_read_single(pmu_fd, &ts[1]) - val; > + > + igt_debug("gt%u: slept=%lu, perf=%"PRIu64"\n", > + gt, slept, val); > + > + igt_debug("Start res: %lu, end_res: %lu", start, end); > + > + assert_within_epsilon(val, > + (ts[1] - ts[0])/USEC_PER_SEC, > + tolerance); > + close(pmu_fd); > +} > + > +igt_main > +{ > + int fd, gt; > + > + igt_fixture { > + fd = drm_open_driver(DRIVER_XE); > + igt_require(!IS_PONTEVECCHIO(xe_dev_id(fd))); > + } > + > + igt_describe("Validate PMU gt-c6 residency counters when idle"); > + igt_subtest("gt-c6-idle") > + xe_for_each_gt(fd, gt) > + test_gt_c6_idle(fd, gt); > + > + igt_fixture { > + close(fd); > + } > +} > diff --git a/tests/meson.build b/tests/meson.build > index 33dffad31..d20f50766 100644 > --- a/tests/meson.build > +++ b/tests/meson.build > @@ -309,6 +309,7 @@ intel_xe_progs = [ > 'xe_pat', > 'xe_peer2peer', > 'xe_pm', > + 'xe_pmu', > 'xe_pm_residency', Why not after xe_pm_residency? Regards, Kamil > 'xe_prime_self_import', > 'xe_query', > -- > 2.38.1 >
diff --git a/tests/intel/xe_pmu.c b/tests/intel/xe_pmu.c new file mode 100644 index 000000000..44589cb86 --- /dev/null +++ b/tests/intel/xe_pmu.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2025 Intel Corporation + */ + +/** + * TEST: Test Xe PMU functionality + * Category: Perf Monitoring Unit + * Mega feature: Perf Monitoring Unit + * Sub-category: Telemetry + * Functionality: Power/Perf + * Test category: Functional tests + */ + +#include <fcntl.h> +#include <limits.h> +#include <time.h> +#include <errno.h> +#include <dirent.h> +#include <string.h> +#include <sys/time.h> + +#include "igt.h" +#include "igt_device.h" +#include "igt_power.h" +#include "igt_sysfs.h" +#include "igt_perf.h" + +#include "lib/igt_syncobj.h" +#include "xe/xe_ioctl.h" +#include "xe/xe_gt.h" +#include "xe/xe_query.h" +#include "xe/xe_spin.h" +#include "xe/xe_util.h" + +#define SLEEP_DURATION 2 /* in seconds */ +const double tolerance = 0.1; +const char *no_debug_data = "\0"; + +static int open_pmu(int xe, uint64_t config) +{ + int fd; + + fd = perf_xe_open(xe, config); + igt_skip_on(fd < 0 && errno == ENODEV); + igt_assert(fd >= 0); + + return fd; +} + +static uint64_t __pmu_read_single(int fd, uint64_t *ts) +{ + uint64_t data[2]; + + igt_assert_eq(read(fd, data, sizeof(data)), sizeof(data)); + if (ts) + *ts = data[1]; + + return data[0]; +} + +static unsigned long read_idle_residency(int fd, int gt) +{ + unsigned long residency = 0; + int gt_fd; + + gt_fd = xe_sysfs_gt_open(fd, gt); + igt_assert(gt_fd >= 0); + igt_assert(igt_sysfs_scanf(gt_fd, "gtidle/idle_residency_ms", "%lu", &residency) == 1); + close(gt_fd); + + return residency; +} + +static u64 get_event_config(int xe, unsigned int gt, char *event) +{ + int ret; + char xe_device[100]; + u64 pmu_config; + u32 start, end; + + xe_perf_device(xe, xe_device, sizeof(xe_device)); + ret = perf_event_config(xe_device, event, &pmu_config); + igt_assert(ret >= 0); + ret = perf_event_format(xe_device, "gt", &start, &end); + igt_assert(ret >= 0); + pmu_config |= (u64) gt << start; + + return pmu_config; +} + +/** + * SUBTEST: gt-c6-idle + * Description: Basic residency test to validate idle residency + * measured over a time interval is within the tolerance + */ +static void test_gt_c6_idle(int xe, unsigned int gt) +{ + int pmu_fd; + u64 pmu_config; + char event[100]; + uint64_t ts[2]; + unsigned long slept, start, end; + uint64_t val; + + /* Get the PMU config for the gt-c6 event */ + sprintf(event, "gt-c6-residency"); + pmu_config = get_event_config(xe, gt, event); + + pmu_fd = open_pmu(xe, pmu_config); + + igt_require_f(igt_wait(xe_gt_is_in_c6(xe, gt), 1000, 10), "GT %d should be in C6\n", gt); + + /* While idle check full RC6. */ + start = read_idle_residency(xe, gt); + val = __pmu_read_single(pmu_fd, &ts[0]); + slept = igt_measured_usleep(SLEEP_DURATION * USEC_PER_SEC) / 1000; + end = read_idle_residency(xe, gt); + val = __pmu_read_single(pmu_fd, &ts[1]) - val; + + igt_debug("gt%u: slept=%lu, perf=%"PRIu64"\n", + gt, slept, val); + + igt_debug("Start res: %lu, end_res: %lu", start, end); + + assert_within_epsilon(val, + (ts[1] - ts[0])/USEC_PER_SEC, + tolerance); + close(pmu_fd); +} + +igt_main +{ + int fd, gt; + + igt_fixture { + fd = drm_open_driver(DRIVER_XE); + igt_require(!IS_PONTEVECCHIO(xe_dev_id(fd))); + } + + igt_describe("Validate PMU gt-c6 residency counters when idle"); + igt_subtest("gt-c6-idle") + xe_for_each_gt(fd, gt) + test_gt_c6_idle(fd, gt); + + igt_fixture { + close(fd); + } +} diff --git a/tests/meson.build b/tests/meson.build index 33dffad31..d20f50766 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -309,6 +309,7 @@ intel_xe_progs = [ 'xe_pat', 'xe_peer2peer', 'xe_pm', + 'xe_pmu', 'xe_pm_residency', 'xe_prime_self_import', 'xe_query',
Simple tests for validating the PMU implementation for GT C6 residencies. v2: Rename rc6-residency-* to gt-c6-residency and remove freq tests. v3: Keep just gt-c6 tests, add frequency tests later. v4: Review comments (Riana) v5: Review comments (Lucas) Cc: Lucas De Marchi <lucas.demarchi@intel.com> Cc: Riana Tauro <riana.tauro@intel.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com> --- tests/intel/xe_pmu.c | 149 +++++++++++++++++++++++++++++++++++++++++++ tests/meson.build | 1 + 2 files changed, 150 insertions(+) create mode 100644 tests/intel/xe_pmu.c