i965: perf: add support for userspace configurations
This allows us to deploy new configurations without touching the kernel. v2: Detect loadable configs without creating one (Chris) Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
@@ -1729,6 +1729,18 @@ read_file_uint64(const char *file, uint64_t *val)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
register_oa_config(struct brw_context *brw,
|
||||||
|
const struct brw_perf_query_info *query,
|
||||||
|
uint64_t config_id)
|
||||||
|
{
|
||||||
|
struct brw_perf_query_info *registred_query = append_query_info(brw);
|
||||||
|
*registred_query = *query;
|
||||||
|
registred_query->oa_metrics_set_id = config_id;
|
||||||
|
DBG("metric set registred: id = %" PRIu64", guid = %s\n",
|
||||||
|
registred_query->oa_metrics_set_id, query->guid);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
enumerate_sysfs_metrics(struct brw_context *brw, const char *sysfs_dev_dir)
|
enumerate_sysfs_metrics(struct brw_context *brw, const char *sysfs_dev_dir)
|
||||||
{
|
{
|
||||||
@@ -1761,7 +1773,6 @@ enumerate_sysfs_metrics(struct brw_context *brw, const char *sysfs_dev_dir)
|
|||||||
entry = _mesa_hash_table_search(brw->perfquery.oa_metrics_table,
|
entry = _mesa_hash_table_search(brw->perfquery.oa_metrics_table,
|
||||||
metric_entry->d_name);
|
metric_entry->d_name);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
struct brw_perf_query_info *query;
|
|
||||||
uint64_t id;
|
uint64_t id;
|
||||||
|
|
||||||
len = snprintf(buf, sizeof(buf), "%s/metrics/%s/id",
|
len = snprintf(buf, sizeof(buf), "%s/metrics/%s/id",
|
||||||
@@ -1776,12 +1787,7 @@ enumerate_sysfs_metrics(struct brw_context *brw, const char *sysfs_dev_dir)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
query = append_query_info(brw);
|
register_oa_config(brw, (const struct brw_perf_query_info *)entry->data, id);
|
||||||
*query = *(struct brw_perf_query_info *)entry->data;
|
|
||||||
query->oa_metrics_set_id = id;
|
|
||||||
|
|
||||||
DBG("metric set known by mesa: id = %" PRIu64"\n",
|
|
||||||
query->oa_metrics_set_id);
|
|
||||||
} else
|
} else
|
||||||
DBG("metric set not known by mesa (skipping)\n");
|
DBG("metric set not known by mesa (skipping)\n");
|
||||||
}
|
}
|
||||||
@@ -1807,6 +1813,90 @@ read_sysfs_drm_device_file_uint64(struct brw_context *brw,
|
|||||||
return read_file_uint64(buf, value);
|
return read_file_uint64(buf, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
kernel_has_dynamic_config_support(struct brw_context *brw,
|
||||||
|
const char *sysfs_dev_dir)
|
||||||
|
{
|
||||||
|
__DRIscreen *screen = brw->screen->driScrnPriv;
|
||||||
|
struct hash_entry *entry;
|
||||||
|
|
||||||
|
hash_table_foreach(brw->perfquery.oa_metrics_table, entry) {
|
||||||
|
struct brw_perf_query_info *query = entry->data;
|
||||||
|
char config_path[256];
|
||||||
|
uint64_t config_id;
|
||||||
|
|
||||||
|
snprintf(config_path, sizeof(config_path),
|
||||||
|
"%s/metrics/%s/id", sysfs_dev_dir, query->guid);
|
||||||
|
|
||||||
|
/* Look for the test config, which we know we can't replace. */
|
||||||
|
if (read_file_uint64(config_path, &config_id) && config_id == 1) {
|
||||||
|
uint32_t mux_regs[] = { 0x9888 /* NOA_WRITE */, 0x0 };
|
||||||
|
struct drm_i915_perf_oa_config config;
|
||||||
|
|
||||||
|
memset(&config, 0, sizeof(config));
|
||||||
|
|
||||||
|
memcpy(config.uuid, query->guid, sizeof(config.uuid));
|
||||||
|
|
||||||
|
config.n_mux_regs = 1;
|
||||||
|
config.mux_regs_ptr = (uintptr_t) mux_regs;
|
||||||
|
|
||||||
|
if (ioctl(screen->fd, DRM_IOCTL_I915_PERF_REMOVE_CONFIG, &config_id) < 0 &&
|
||||||
|
errno == ENOENT)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_oa_configs(struct brw_context *brw, const char *sysfs_dev_dir)
|
||||||
|
{
|
||||||
|
__DRIscreen *screen = brw->screen->driScrnPriv;
|
||||||
|
struct hash_entry *entry;
|
||||||
|
|
||||||
|
hash_table_foreach(brw->perfquery.oa_metrics_table, entry) {
|
||||||
|
const struct brw_perf_query_info *query = entry->data;
|
||||||
|
struct drm_i915_perf_oa_config config;
|
||||||
|
char config_path[256];
|
||||||
|
uint64_t config_id;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
snprintf(config_path, sizeof(config_path),
|
||||||
|
"%s/metrics/%s/id", sysfs_dev_dir, query->guid);
|
||||||
|
|
||||||
|
/* Don't recreate already loaded configs. */
|
||||||
|
if (read_file_uint64(config_path, &config_id)) {
|
||||||
|
register_oa_config(brw, query, config_id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&config, 0, sizeof(config));
|
||||||
|
|
||||||
|
memcpy(config.uuid, query->guid, sizeof(config.uuid));
|
||||||
|
|
||||||
|
config.n_mux_regs = query->n_mux_regs;
|
||||||
|
config.mux_regs_ptr = (uintptr_t) query->mux_regs;
|
||||||
|
|
||||||
|
config.n_boolean_regs = query->n_b_counter_regs;
|
||||||
|
config.boolean_regs_ptr = (uintptr_t) query->b_counter_regs;
|
||||||
|
|
||||||
|
config.n_flex_regs = query->n_flex_regs;
|
||||||
|
config.flex_regs_ptr = (uintptr_t) query->flex_regs;
|
||||||
|
|
||||||
|
ret = ioctl(screen->fd, DRM_IOCTL_I915_PERF_ADD_CONFIG, &config);
|
||||||
|
if (ret < 0) {
|
||||||
|
DBG("Failed to load \"%s\" (%s) metrics set in kernel: %s\n",
|
||||||
|
query->name, query->guid, strerror(errno));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
register_oa_config(brw, query, config_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
init_oa_sys_vars(struct brw_context *brw, const char *sysfs_dev_dir)
|
init_oa_sys_vars(struct brw_context *brw, const char *sysfs_dev_dir)
|
||||||
{
|
{
|
||||||
@@ -2054,7 +2144,10 @@ brw_init_perf_query_info(struct gl_context *ctx)
|
|||||||
*/
|
*/
|
||||||
oa_register(brw);
|
oa_register(brw);
|
||||||
|
|
||||||
enumerate_sysfs_metrics(brw, sysfs_dev_dir);
|
if (kernel_has_dynamic_config_support(brw, sysfs_dev_dir))
|
||||||
|
init_oa_configs(brw, sysfs_dev_dir);
|
||||||
|
else
|
||||||
|
enumerate_sysfs_metrics(brw, sysfs_dev_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
brw->perfquery.unaccumulated =
|
brw->perfquery.unaccumulated =
|
||||||
|
Reference in New Issue
Block a user