Message ID | 20250407234406.4084642-3-vinay.belgaumkar@intel.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Add PMU test for GT frequency | expand |
Hi Vinay On 4/8/2025 5:14 AM, Vinay Belgaumkar wrote: > Add a basic test that uses PMU to read GT actual and requested > frequencies while running a workload. > > v2: Rebase and comments (Riana) > > Cc: Lucas De Marchi <lucas.demarchi@intel.com> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> > Cc: Riana Tauro <riana.tauro@intel.com> > Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com> > --- > tests/intel/xe_pmu.c | 128 ++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 127 insertions(+), 1 deletion(-) > > diff --git a/tests/intel/xe_pmu.c b/tests/intel/xe_pmu.c > index 175bbf374..fbac9c798 100644 > --- a/tests/intel/xe_pmu.c > +++ b/tests/intel/xe_pmu.c > @@ -376,6 +376,94 @@ static void test_gt_c6_idle(int xe, unsigned int gt) > close(pmu_fd); > } > > +/** > + * SUBTEST: gt-frequency > + * Description: Validate we can collect accurate frequency PMU stats > + * while running a workload. > + */ > +static void test_gt_frequency(int fd, struct drm_xe_engine_class_instance *eci) > +{ > + struct xe_cork *cork = NULL; > + uint64_t end[2], start[2]; > + unsigned long config_rq_freq, config_act_freq; > + double min[2], max[2]; > + uint32_t gt = eci->gt_id; > + uint32_t orig_min = xe_gt_get_freq(fd, eci->gt_id, "min"); > + uint32_t orig_max = xe_gt_get_freq(fd, eci->gt_id, "max"); > + uint32_t vm; > + int pmu_fd[2]; > + > + config_rq_freq = get_event_config(gt, NULL, "gt-requested-frequency"); > + pmu_fd[0] = open_group(fd, config_rq_freq, -1); > + > + config_act_freq = get_event_config(gt, NULL, "gt-actual-frequency"); > + pmu_fd[1] = open_group(fd, config_act_freq, pmu_fd[0]); > + > + vm = xe_vm_create(fd, 0, 0); > + > + cork = xe_cork_create_opts(fd, eci, vm, 1, 1); > + xe_cork_sync_start(fd, cork); > + > + /* > + * Set GPU to min frequency and read PMU counters. > + */ > + igt_assert(xe_gt_set_freq(fd, gt, "max", orig_min) > 0); > + igt_assert(xe_gt_get_freq(fd, gt, "max") == orig_min); > + > + pmu_read_multi(pmu_fd[0], 2, start); > + usleep(SLEEP_DURATION * USEC_PER_SEC); > + pmu_read_multi(pmu_fd[0], 2, end); > + > + min[0] = (end[0] - start[0]); > + min[1] = (end[1] - start[1]); > + > + /* > + * Set GPU to max frequency and read PMU counters. > + */ > + igt_assert(xe_gt_set_freq(fd, gt, "max", orig_max) > 0); > + igt_assert(xe_gt_get_freq(fd, gt, "max") == orig_max); > + igt_assert(xe_gt_set_freq(fd, gt, "min", orig_max) > 0); > + igt_assert(xe_gt_get_freq(fd, gt, "min") == orig_max); > + > + pmu_read_multi(pmu_fd[0], 2, start); > + usleep(SLEEP_DURATION * USEC_PER_SEC); > + pmu_read_multi(pmu_fd[0], 2, end); > + > + max[0] = (end[0] - start[0]); > + max[1] = (end[1] - start[1]); > + > + xe_cork_sync_end(fd, cork); > + > + /* > + * Restore min/max. > + */ > + igt_assert(xe_gt_set_freq(fd, gt, "min", orig_min) > 0); > + igt_assert(xe_gt_get_freq(fd, gt, "min") == orig_min); > + > + igt_info("Minimum frequency: requested %.1f, actual %.1f\n", > + min[0], min[1]); > + igt_info("Maximum frequency: requested %.1f, actual %.1f\n", > + max[0], max[1]); > + > + close(pmu_fd[0]); > + close(pmu_fd[1]); > + > + if (cork) > + xe_cork_destroy(fd, cork); > + > + xe_vm_destroy(fd, vm); > + > + close(pmu_fd[0]); > + close(pmu_fd[1]); > + > + assert_within_epsilon(min[0], orig_min, tolerance); > + /* > + * On thermally throttled devices we cannot be sure maximum frequency > + * can be reached so use larger tolerance downwards. > + */ > + assert_within_epsilon_up_down(max[0], orig_max, tolerance, 0.15f); > +} > + > static unsigned int enable_and_provision_vfs(int fd) > { > unsigned int gt, num_vfs; > @@ -429,8 +517,9 @@ static void disable_vfs(int fd) > > igt_main > { > - int fd, gt; > + int fd, gt, num_gts; > struct drm_xe_engine_class_instance *eci; > + uint32_t *stash_min, *stash_max; > > igt_fixture { > fd = drm_open_driver(DRIVER_XE); > @@ -482,6 +571,43 @@ igt_main > disable_vfs(fd); > } > > + igt_subtest_group { > + igt_fixture { > + igt_require(xe_sysfs_gt_has_node(fd, 0, "freq0")); > + num_gts = xe_number_gt(fd); > + > + stash_min = (uint32_t *) malloc(sizeof(uint32_t) * num_gts); > + stash_max = (uint32_t *) malloc(sizeof(uint32_t) * num_gts); > + > + xe_for_each_gt(fd, gt) { > + stash_min[gt] = xe_gt_get_freq(fd, gt, "min"); > + stash_max[gt] = xe_gt_get_freq(fd, gt, "max"); This can be moved inside the igt_subtest with local variables since it's only one test. The subtest group is executed for all the other tests too Thanks Riana> + } > + } > + > + igt_describe("Validate PMU GT freq measured is within the tolerance"); > + igt_subtest_with_dynamic("gt-frequency") { > + xe_for_each_gt(fd, gt) { > + igt_dynamic_f("gt%u", gt) > + xe_for_each_engine(fd, eci) { > + if (gt == eci->gt_id) { > + test_gt_frequency(fd, eci); > + break; > + } > + } > + } > + } > + > + igt_fixture { > + xe_for_each_gt(fd, gt) { > + xe_gt_set_freq(fd, gt, "max", stash_max[gt]); > + xe_gt_set_freq(fd, gt, "min", stash_min[gt]); > + } > + free(stash_min); > + free(stash_max); > + } > + } > + > igt_fixture { > close(fd); > }
Hi, On 2025-04-09 at 15:28:59 +0530, Riana Tauro wrote: > Hi Vinay > > On 4/8/2025 5:14 AM, Vinay Belgaumkar wrote: > > Add a basic test that uses PMU to read GT actual and requested > > frequencies while running a workload. > > > > v2: Rebase and comments (Riana) > > > > Cc: Lucas De Marchi <lucas.demarchi@intel.com> > > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> > > Cc: Riana Tauro <riana.tauro@intel.com> > > Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com> > > --- > > tests/intel/xe_pmu.c | 128 ++++++++++++++++++++++++++++++++++++++++++- > > 1 file changed, 127 insertions(+), 1 deletion(-) > > > > diff --git a/tests/intel/xe_pmu.c b/tests/intel/xe_pmu.c > > index 175bbf374..fbac9c798 100644 > > --- a/tests/intel/xe_pmu.c > > +++ b/tests/intel/xe_pmu.c > > @@ -376,6 +376,94 @@ static void test_gt_c6_idle(int xe, unsigned int gt) > > close(pmu_fd); > > } > > +/** > > + * SUBTEST: gt-frequency > > + * Description: Validate we can collect accurate frequency PMU stats > > + * while running a workload. > > + */ > > +static void test_gt_frequency(int fd, struct drm_xe_engine_class_instance *eci) > > +{ > > + struct xe_cork *cork = NULL; > > + uint64_t end[2], start[2]; > > + unsigned long config_rq_freq, config_act_freq; > > + double min[2], max[2]; > > + uint32_t gt = eci->gt_id; > > + uint32_t orig_min = xe_gt_get_freq(fd, eci->gt_id, "min"); > > + uint32_t orig_max = xe_gt_get_freq(fd, eci->gt_id, "max"); > > + uint32_t vm; > > + int pmu_fd[2]; > > + > > + config_rq_freq = get_event_config(gt, NULL, "gt-requested-frequency"); > > + pmu_fd[0] = open_group(fd, config_rq_freq, -1); > > + > > + config_act_freq = get_event_config(gt, NULL, "gt-actual-frequency"); > > + pmu_fd[1] = open_group(fd, config_act_freq, pmu_fd[0]); > > + > > + vm = xe_vm_create(fd, 0, 0); > > + > > + cork = xe_cork_create_opts(fd, eci, vm, 1, 1); > > + xe_cork_sync_start(fd, cork); > > + > > + /* > > + * Set GPU to min frequency and read PMU counters. > > + */ > > + igt_assert(xe_gt_set_freq(fd, gt, "max", orig_min) > 0); > > + igt_assert(xe_gt_get_freq(fd, gt, "max") == orig_min); > > + > > + pmu_read_multi(pmu_fd[0], 2, start); > > + usleep(SLEEP_DURATION * USEC_PER_SEC); > > + pmu_read_multi(pmu_fd[0], 2, end); > > + > > + min[0] = (end[0] - start[0]); > > + min[1] = (end[1] - start[1]); > > + > > + /* > > + * Set GPU to max frequency and read PMU counters. > > + */ > > + igt_assert(xe_gt_set_freq(fd, gt, "max", orig_max) > 0); > > + igt_assert(xe_gt_get_freq(fd, gt, "max") == orig_max); > > + igt_assert(xe_gt_set_freq(fd, gt, "min", orig_max) > 0); > > + igt_assert(xe_gt_get_freq(fd, gt, "min") == orig_max); > > + > > + pmu_read_multi(pmu_fd[0], 2, start); > > + usleep(SLEEP_DURATION * USEC_PER_SEC); > > + pmu_read_multi(pmu_fd[0], 2, end); > > + > > + max[0] = (end[0] - start[0]); > > + max[1] = (end[1] - start[1]); > > + > > + xe_cork_sync_end(fd, cork); > > + > > + /* > > + * Restore min/max. > > + */ > > + igt_assert(xe_gt_set_freq(fd, gt, "min", orig_min) > 0); > > + igt_assert(xe_gt_get_freq(fd, gt, "min") == orig_min); > > + > > + igt_info("Minimum frequency: requested %.1f, actual %.1f\n", > > + min[0], min[1]); > > + igt_info("Maximum frequency: requested %.1f, actual %.1f\n", > > + max[0], max[1]); > > + > > + close(pmu_fd[0]); > > + close(pmu_fd[1]); > > + > > + if (cork) > > + xe_cork_destroy(fd, cork); > > + > > + xe_vm_destroy(fd, vm); > > + > > + close(pmu_fd[0]); > > + close(pmu_fd[1]); > > + > > + assert_within_epsilon(min[0], orig_min, tolerance); > > + /* > > + * On thermally throttled devices we cannot be sure maximum frequency > > + * can be reached so use larger tolerance downwards. > > + */ > > + assert_within_epsilon_up_down(max[0], orig_max, tolerance, 0.15f); > > +} > > + > > static unsigned int enable_and_provision_vfs(int fd) > > { > > unsigned int gt, num_vfs; > > @@ -429,8 +517,9 @@ static void disable_vfs(int fd) > > igt_main > > { > > - int fd, gt; > > + int fd, gt, num_gts; > > struct drm_xe_engine_class_instance *eci; > > + uint32_t *stash_min, *stash_max; > > igt_fixture { > > fd = drm_open_driver(DRIVER_XE); > > @@ -482,6 +571,43 @@ igt_main > > disable_vfs(fd); > > } > > + igt_subtest_group { Add here: bool has_freq0_node, needs_restore = false; > > + igt_fixture { > > + igt_require(xe_sysfs_gt_has_node(fd, 0, "freq0")); Move this require into subtest. If you need it here then remember its value for later use: has_freq0_node = xe_sysfs_gt_has_node(fd, 0, "freq0"); > > + num_gts = xe_number_gt(fd); > > + So here start with if: if (has_freq0_node) { > > + stash_min = (uint32_t *) malloc(sizeof(uint32_t) * num_gts); > > + stash_max = (uint32_t *) malloc(sizeof(uint32_t) * num_gts); > > + > > + xe_for_each_gt(fd, gt) { > > + stash_min[gt] = xe_gt_get_freq(fd, gt, "min"); > > + stash_max[gt] = xe_gt_get_freq(fd, gt, "max"); > This can be moved inside the igt_subtest with local variables since it's > only one test. The subtest group is executed for all the other tests too > > Thanks > Riana> + } > > + } > > + > > + igt_describe("Validate PMU GT freq measured is within the tolerance"); > > + igt_subtest_with_dynamic("gt-frequency") { needs_restore = true; > > + xe_for_each_gt(fd, gt) { > > + igt_dynamic_f("gt%u", gt) > > + xe_for_each_engine(fd, eci) { > > + if (gt == eci->gt_id) { > > + test_gt_frequency(fd, eci); > > + break; > > + } > > + } > > + } > > + } > > + > > + igt_fixture { if (needs_restore) { > > + xe_for_each_gt(fd, gt) { > > + xe_gt_set_freq(fd, gt, "max", stash_max[gt]); > > + xe_gt_set_freq(fd, gt, "min", stash_min[gt]); > > + } > > + free(stash_min); > > + free(stash_max); } /* restore */ Regards, Kamil > > + } > > + } > > + > > igt_fixture { > > close(fd); > > } >
On 4/9/2025 4:06 AM, Kamil Konieczny wrote: > Hi, > On 2025-04-09 at 15:28:59 +0530, Riana Tauro wrote: >> Hi Vinay >> >> On 4/8/2025 5:14 AM, Vinay Belgaumkar wrote: >>> Add a basic test that uses PMU to read GT actual and requested >>> frequencies while running a workload. >>> >>> v2: Rebase and comments (Riana) >>> >>> Cc: Lucas De Marchi <lucas.demarchi@intel.com> >>> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> >>> Cc: Riana Tauro <riana.tauro@intel.com> >>> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com> >>> --- >>> tests/intel/xe_pmu.c | 128 ++++++++++++++++++++++++++++++++++++++++++- >>> 1 file changed, 127 insertions(+), 1 deletion(-) >>> >>> diff --git a/tests/intel/xe_pmu.c b/tests/intel/xe_pmu.c >>> index 175bbf374..fbac9c798 100644 >>> --- a/tests/intel/xe_pmu.c >>> +++ b/tests/intel/xe_pmu.c >>> @@ -376,6 +376,94 @@ static void test_gt_c6_idle(int xe, unsigned int gt) >>> close(pmu_fd); >>> } >>> +/** >>> + * SUBTEST: gt-frequency >>> + * Description: Validate we can collect accurate frequency PMU stats >>> + * while running a workload. >>> + */ >>> +static void test_gt_frequency(int fd, struct drm_xe_engine_class_instance *eci) >>> +{ >>> + struct xe_cork *cork = NULL; >>> + uint64_t end[2], start[2]; >>> + unsigned long config_rq_freq, config_act_freq; >>> + double min[2], max[2]; >>> + uint32_t gt = eci->gt_id; >>> + uint32_t orig_min = xe_gt_get_freq(fd, eci->gt_id, "min"); >>> + uint32_t orig_max = xe_gt_get_freq(fd, eci->gt_id, "max"); >>> + uint32_t vm; >>> + int pmu_fd[2]; >>> + >>> + config_rq_freq = get_event_config(gt, NULL, "gt-requested-frequency"); >>> + pmu_fd[0] = open_group(fd, config_rq_freq, -1); >>> + >>> + config_act_freq = get_event_config(gt, NULL, "gt-actual-frequency"); >>> + pmu_fd[1] = open_group(fd, config_act_freq, pmu_fd[0]); >>> + >>> + vm = xe_vm_create(fd, 0, 0); >>> + >>> + cork = xe_cork_create_opts(fd, eci, vm, 1, 1); >>> + xe_cork_sync_start(fd, cork); >>> + >>> + /* >>> + * Set GPU to min frequency and read PMU counters. >>> + */ >>> + igt_assert(xe_gt_set_freq(fd, gt, "max", orig_min) > 0); >>> + igt_assert(xe_gt_get_freq(fd, gt, "max") == orig_min); >>> + >>> + pmu_read_multi(pmu_fd[0], 2, start); >>> + usleep(SLEEP_DURATION * USEC_PER_SEC); >>> + pmu_read_multi(pmu_fd[0], 2, end); >>> + >>> + min[0] = (end[0] - start[0]); >>> + min[1] = (end[1] - start[1]); >>> + >>> + /* >>> + * Set GPU to max frequency and read PMU counters. >>> + */ >>> + igt_assert(xe_gt_set_freq(fd, gt, "max", orig_max) > 0); >>> + igt_assert(xe_gt_get_freq(fd, gt, "max") == orig_max); >>> + igt_assert(xe_gt_set_freq(fd, gt, "min", orig_max) > 0); >>> + igt_assert(xe_gt_get_freq(fd, gt, "min") == orig_max); >>> + >>> + pmu_read_multi(pmu_fd[0], 2, start); >>> + usleep(SLEEP_DURATION * USEC_PER_SEC); >>> + pmu_read_multi(pmu_fd[0], 2, end); >>> + >>> + max[0] = (end[0] - start[0]); >>> + max[1] = (end[1] - start[1]); >>> + >>> + xe_cork_sync_end(fd, cork); >>> + >>> + /* >>> + * Restore min/max. >>> + */ >>> + igt_assert(xe_gt_set_freq(fd, gt, "min", orig_min) > 0); >>> + igt_assert(xe_gt_get_freq(fd, gt, "min") == orig_min); >>> + >>> + igt_info("Minimum frequency: requested %.1f, actual %.1f\n", >>> + min[0], min[1]); >>> + igt_info("Maximum frequency: requested %.1f, actual %.1f\n", >>> + max[0], max[1]); >>> + >>> + close(pmu_fd[0]); >>> + close(pmu_fd[1]); >>> + >>> + if (cork) >>> + xe_cork_destroy(fd, cork); >>> + >>> + xe_vm_destroy(fd, vm); >>> + >>> + close(pmu_fd[0]); >>> + close(pmu_fd[1]); >>> + >>> + assert_within_epsilon(min[0], orig_min, tolerance); >>> + /* >>> + * On thermally throttled devices we cannot be sure maximum frequency >>> + * can be reached so use larger tolerance downwards. >>> + */ >>> + assert_within_epsilon_up_down(max[0], orig_max, tolerance, 0.15f); >>> +} >>> + >>> static unsigned int enable_and_provision_vfs(int fd) >>> { >>> unsigned int gt, num_vfs; >>> @@ -429,8 +517,9 @@ static void disable_vfs(int fd) >>> igt_main >>> { >>> - int fd, gt; >>> + int fd, gt, num_gts; >>> struct drm_xe_engine_class_instance *eci; >>> + uint32_t *stash_min, *stash_max; >>> igt_fixture { >>> fd = drm_open_driver(DRIVER_XE); >>> @@ -482,6 +571,43 @@ igt_main >>> disable_vfs(fd); >>> } >>> + igt_subtest_group { > Add here: > bool has_freq0_node, needs_restore = false; > >>> + igt_fixture { >>> + igt_require(xe_sysfs_gt_has_node(fd, 0, "freq0")); > Move this require into subtest. If you need it here then remember its > value for later use: > has_freq0_node = xe_sysfs_gt_has_node(fd, 0, "freq0"); > >>> + num_gts = xe_number_gt(fd); >>> + > So here start with if: > > if (has_freq0_node) { > >>> + stash_min = (uint32_t *) malloc(sizeof(uint32_t) * num_gts); >>> + stash_max = (uint32_t *) malloc(sizeof(uint32_t) * num_gts); >>> + >>> + xe_for_each_gt(fd, gt) { >>> + stash_min[gt] = xe_gt_get_freq(fd, gt, "min"); >>> + stash_max[gt] = xe_gt_get_freq(fd, gt, "max"); >> This can be moved inside the igt_subtest with local variables since it's >> only one test. The subtest group is executed for all the other tests too >> >> Thanks >> Riana> + } >>> + } >>> + >>> + igt_describe("Validate PMU GT freq measured is within the tolerance"); >>> + igt_subtest_with_dynamic("gt-frequency") { > needs_restore = true; > >>> + xe_for_each_gt(fd, gt) { >>> + igt_dynamic_f("gt%u", gt) >>> + xe_for_each_engine(fd, eci) { >>> + if (gt == eci->gt_id) { >>> + test_gt_frequency(fd, eci); >>> + break; >>> + } >>> + } >>> + } >>> + } >>> + >>> + igt_fixture { > if (needs_restore) { ok. Thanks, Vinay. > >>> + xe_for_each_gt(fd, gt) { >>> + xe_gt_set_freq(fd, gt, "max", stash_max[gt]); >>> + xe_gt_set_freq(fd, gt, "min", stash_min[gt]); >>> + } >>> + free(stash_min); >>> + free(stash_max); > } /* restore */ > > Regards, > Kamil > >>> + } >>> + } >>> + >>> igt_fixture { >>> close(fd); >>> }
On 4/9/2025 2:58 AM, Riana Tauro wrote: > Hi Vinay > > On 4/8/2025 5:14 AM, Vinay Belgaumkar wrote: >> Add a basic test that uses PMU to read GT actual and requested >> frequencies while running a workload. >> >> v2: Rebase and comments (Riana) >> >> Cc: Lucas De Marchi <lucas.demarchi@intel.com> >> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> >> Cc: Riana Tauro <riana.tauro@intel.com> >> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com> >> --- >> tests/intel/xe_pmu.c | 128 ++++++++++++++++++++++++++++++++++++++++++- >> 1 file changed, 127 insertions(+), 1 deletion(-) >> >> diff --git a/tests/intel/xe_pmu.c b/tests/intel/xe_pmu.c >> index 175bbf374..fbac9c798 100644 >> --- a/tests/intel/xe_pmu.c >> +++ b/tests/intel/xe_pmu.c >> @@ -376,6 +376,94 @@ static void test_gt_c6_idle(int xe, unsigned int >> gt) >> close(pmu_fd); >> } >> +/** >> + * SUBTEST: gt-frequency >> + * Description: Validate we can collect accurate frequency PMU stats >> + * while running a workload. >> + */ >> +static void test_gt_frequency(int fd, struct >> drm_xe_engine_class_instance *eci) >> +{ >> + struct xe_cork *cork = NULL; >> + uint64_t end[2], start[2]; >> + unsigned long config_rq_freq, config_act_freq; >> + double min[2], max[2]; >> + uint32_t gt = eci->gt_id; >> + uint32_t orig_min = xe_gt_get_freq(fd, eci->gt_id, "min"); >> + uint32_t orig_max = xe_gt_get_freq(fd, eci->gt_id, "max"); >> + uint32_t vm; >> + int pmu_fd[2]; >> + >> + config_rq_freq = get_event_config(gt, NULL, >> "gt-requested-frequency"); >> + pmu_fd[0] = open_group(fd, config_rq_freq, -1); >> + >> + config_act_freq = get_event_config(gt, NULL, >> "gt-actual-frequency"); >> + pmu_fd[1] = open_group(fd, config_act_freq, pmu_fd[0]); >> + >> + vm = xe_vm_create(fd, 0, 0); >> + >> + cork = xe_cork_create_opts(fd, eci, vm, 1, 1); >> + xe_cork_sync_start(fd, cork); >> + >> + /* >> + * Set GPU to min frequency and read PMU counters. >> + */ >> + igt_assert(xe_gt_set_freq(fd, gt, "max", orig_min) > 0); >> + igt_assert(xe_gt_get_freq(fd, gt, "max") == orig_min); >> + >> + pmu_read_multi(pmu_fd[0], 2, start); >> + usleep(SLEEP_DURATION * USEC_PER_SEC); >> + pmu_read_multi(pmu_fd[0], 2, end); >> + >> + min[0] = (end[0] - start[0]); >> + min[1] = (end[1] - start[1]); >> + >> + /* >> + * Set GPU to max frequency and read PMU counters. >> + */ >> + igt_assert(xe_gt_set_freq(fd, gt, "max", orig_max) > 0); >> + igt_assert(xe_gt_get_freq(fd, gt, "max") == orig_max); >> + igt_assert(xe_gt_set_freq(fd, gt, "min", orig_max) > 0); >> + igt_assert(xe_gt_get_freq(fd, gt, "min") == orig_max); >> + >> + pmu_read_multi(pmu_fd[0], 2, start); >> + usleep(SLEEP_DURATION * USEC_PER_SEC); >> + pmu_read_multi(pmu_fd[0], 2, end); >> + >> + max[0] = (end[0] - start[0]); >> + max[1] = (end[1] - start[1]); >> + >> + xe_cork_sync_end(fd, cork); >> + >> + /* >> + * Restore min/max. >> + */ >> + igt_assert(xe_gt_set_freq(fd, gt, "min", orig_min) > 0); >> + igt_assert(xe_gt_get_freq(fd, gt, "min") == orig_min); >> + >> + igt_info("Minimum frequency: requested %.1f, actual %.1f\n", >> + min[0], min[1]); >> + igt_info("Maximum frequency: requested %.1f, actual %.1f\n", >> + max[0], max[1]); >> + >> + close(pmu_fd[0]); >> + close(pmu_fd[1]); >> + >> + if (cork) >> + xe_cork_destroy(fd, cork); >> + >> + xe_vm_destroy(fd, vm); >> + >> + close(pmu_fd[0]); >> + close(pmu_fd[1]); >> + >> + assert_within_epsilon(min[0], orig_min, tolerance); >> + /* >> + * On thermally throttled devices we cannot be sure maximum >> frequency >> + * can be reached so use larger tolerance downwards. >> + */ >> + assert_within_epsilon_up_down(max[0], orig_max, tolerance, 0.15f); >> +} >> + >> static unsigned int enable_and_provision_vfs(int fd) >> { >> unsigned int gt, num_vfs; >> @@ -429,8 +517,9 @@ static void disable_vfs(int fd) >> igt_main >> { >> - int fd, gt; >> + int fd, gt, num_gts; >> struct drm_xe_engine_class_instance *eci; >> + uint32_t *stash_min, *stash_max; >> igt_fixture { >> fd = drm_open_driver(DRIVER_XE); >> @@ -482,6 +571,43 @@ igt_main >> disable_vfs(fd); >> } >> + igt_subtest_group { >> + igt_fixture { >> + igt_require(xe_sysfs_gt_has_node(fd, 0, "freq0")); >> + num_gts = xe_number_gt(fd); >> + >> + stash_min = (uint32_t *) malloc(sizeof(uint32_t) * >> num_gts); >> + stash_max = (uint32_t *) malloc(sizeof(uint32_t) * >> num_gts); >> + >> + xe_for_each_gt(fd, gt) { >> + stash_min[gt] = xe_gt_get_freq(fd, gt, "min"); >> + stash_max[gt] = xe_gt_get_freq(fd, gt, "max"); > This can be moved inside the igt_subtest with local variables since > it's only one test. The subtest group is executed for all the other > tests too ok. Thanks, Vinay. > > Thanks > Riana> + } >> + } >> + >> + igt_describe("Validate PMU GT freq measured is within the >> tolerance"); >> + igt_subtest_with_dynamic("gt-frequency") { >> + xe_for_each_gt(fd, gt) { >> + igt_dynamic_f("gt%u", gt) >> + xe_for_each_engine(fd, eci) { >> + if (gt == eci->gt_id) { >> + test_gt_frequency(fd, eci); >> + break; >> + } >> + } >> + } >> + } >> + >> + igt_fixture { >> + xe_for_each_gt(fd, gt) { >> + xe_gt_set_freq(fd, gt, "max", stash_max[gt]); >> + xe_gt_set_freq(fd, gt, "min", stash_min[gt]); >> + } >> + free(stash_min); >> + free(stash_max); >> + } >> + } >> + >> igt_fixture { >> close(fd); >> } >
diff --git a/tests/intel/xe_pmu.c b/tests/intel/xe_pmu.c index 175bbf374..fbac9c798 100644 --- a/tests/intel/xe_pmu.c +++ b/tests/intel/xe_pmu.c @@ -376,6 +376,94 @@ static void test_gt_c6_idle(int xe, unsigned int gt) close(pmu_fd); } +/** + * SUBTEST: gt-frequency + * Description: Validate we can collect accurate frequency PMU stats + * while running a workload. + */ +static void test_gt_frequency(int fd, struct drm_xe_engine_class_instance *eci) +{ + struct xe_cork *cork = NULL; + uint64_t end[2], start[2]; + unsigned long config_rq_freq, config_act_freq; + double min[2], max[2]; + uint32_t gt = eci->gt_id; + uint32_t orig_min = xe_gt_get_freq(fd, eci->gt_id, "min"); + uint32_t orig_max = xe_gt_get_freq(fd, eci->gt_id, "max"); + uint32_t vm; + int pmu_fd[2]; + + config_rq_freq = get_event_config(gt, NULL, "gt-requested-frequency"); + pmu_fd[0] = open_group(fd, config_rq_freq, -1); + + config_act_freq = get_event_config(gt, NULL, "gt-actual-frequency"); + pmu_fd[1] = open_group(fd, config_act_freq, pmu_fd[0]); + + vm = xe_vm_create(fd, 0, 0); + + cork = xe_cork_create_opts(fd, eci, vm, 1, 1); + xe_cork_sync_start(fd, cork); + + /* + * Set GPU to min frequency and read PMU counters. + */ + igt_assert(xe_gt_set_freq(fd, gt, "max", orig_min) > 0); + igt_assert(xe_gt_get_freq(fd, gt, "max") == orig_min); + + pmu_read_multi(pmu_fd[0], 2, start); + usleep(SLEEP_DURATION * USEC_PER_SEC); + pmu_read_multi(pmu_fd[0], 2, end); + + min[0] = (end[0] - start[0]); + min[1] = (end[1] - start[1]); + + /* + * Set GPU to max frequency and read PMU counters. + */ + igt_assert(xe_gt_set_freq(fd, gt, "max", orig_max) > 0); + igt_assert(xe_gt_get_freq(fd, gt, "max") == orig_max); + igt_assert(xe_gt_set_freq(fd, gt, "min", orig_max) > 0); + igt_assert(xe_gt_get_freq(fd, gt, "min") == orig_max); + + pmu_read_multi(pmu_fd[0], 2, start); + usleep(SLEEP_DURATION * USEC_PER_SEC); + pmu_read_multi(pmu_fd[0], 2, end); + + max[0] = (end[0] - start[0]); + max[1] = (end[1] - start[1]); + + xe_cork_sync_end(fd, cork); + + /* + * Restore min/max. + */ + igt_assert(xe_gt_set_freq(fd, gt, "min", orig_min) > 0); + igt_assert(xe_gt_get_freq(fd, gt, "min") == orig_min); + + igt_info("Minimum frequency: requested %.1f, actual %.1f\n", + min[0], min[1]); + igt_info("Maximum frequency: requested %.1f, actual %.1f\n", + max[0], max[1]); + + close(pmu_fd[0]); + close(pmu_fd[1]); + + if (cork) + xe_cork_destroy(fd, cork); + + xe_vm_destroy(fd, vm); + + close(pmu_fd[0]); + close(pmu_fd[1]); + + assert_within_epsilon(min[0], orig_min, tolerance); + /* + * On thermally throttled devices we cannot be sure maximum frequency + * can be reached so use larger tolerance downwards. + */ + assert_within_epsilon_up_down(max[0], orig_max, tolerance, 0.15f); +} + static unsigned int enable_and_provision_vfs(int fd) { unsigned int gt, num_vfs; @@ -429,8 +517,9 @@ static void disable_vfs(int fd) igt_main { - int fd, gt; + int fd, gt, num_gts; struct drm_xe_engine_class_instance *eci; + uint32_t *stash_min, *stash_max; igt_fixture { fd = drm_open_driver(DRIVER_XE); @@ -482,6 +571,43 @@ igt_main disable_vfs(fd); } + igt_subtest_group { + igt_fixture { + igt_require(xe_sysfs_gt_has_node(fd, 0, "freq0")); + num_gts = xe_number_gt(fd); + + stash_min = (uint32_t *) malloc(sizeof(uint32_t) * num_gts); + stash_max = (uint32_t *) malloc(sizeof(uint32_t) * num_gts); + + xe_for_each_gt(fd, gt) { + stash_min[gt] = xe_gt_get_freq(fd, gt, "min"); + stash_max[gt] = xe_gt_get_freq(fd, gt, "max"); + } + } + + igt_describe("Validate PMU GT freq measured is within the tolerance"); + igt_subtest_with_dynamic("gt-frequency") { + xe_for_each_gt(fd, gt) { + igt_dynamic_f("gt%u", gt) + xe_for_each_engine(fd, eci) { + if (gt == eci->gt_id) { + test_gt_frequency(fd, eci); + break; + } + } + } + } + + igt_fixture { + xe_for_each_gt(fd, gt) { + xe_gt_set_freq(fd, gt, "max", stash_max[gt]); + xe_gt_set_freq(fd, gt, "min", stash_min[gt]); + } + free(stash_min); + free(stash_max); + } + } + igt_fixture { close(fd); }
Add a basic test that uses PMU to read GT actual and requested frequencies while running a workload. v2: Rebase and comments (Riana) Cc: Lucas De Marchi <lucas.demarchi@intel.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: Riana Tauro <riana.tauro@intel.com> Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com> --- tests/intel/xe_pmu.c | 128 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 1 deletion(-)