Commit eec688e1 authored by Robert Bragg's avatar Robert Bragg Committed by Daniel Vetter

drm/i915: Add i915 perf infrastructure

Adds base i915 perf infrastructure for Gen performance metrics.

This adds a DRM_IOCTL_I915_PERF_OPEN ioctl that takes an array of uint64
properties to configure a stream of metrics and returns a new fd usable
with standard VFS system calls including read() to read typed and sized
records; ioctl() to enable or disable capture and poll() to wait for
data.

A stream is opened something like:

  uint64_t properties[] = {
      /* Single context sampling */
      DRM_I915_PERF_PROP_CTX_HANDLE,        ctx_handle,

      /* Include OA reports in samples */
      DRM_I915_PERF_PROP_SAMPLE_OA,         true,

      /* OA unit configuration */
      DRM_I915_PERF_PROP_OA_METRICS_SET,    metrics_set_id,
      DRM_I915_PERF_PROP_OA_FORMAT,         report_format,
      DRM_I915_PERF_PROP_OA_EXPONENT,       period_exponent,
   };
   struct drm_i915_perf_open_param parm = {
      .flags = I915_PERF_FLAG_FD_CLOEXEC |
               I915_PERF_FLAG_FD_NONBLOCK |
               I915_PERF_FLAG_DISABLED,
      .properties_ptr = (uint64_t)properties,
      .num_properties = sizeof(properties) / 16,
   };
   int fd = drmIoctl(drm_fd, DRM_IOCTL_I915_PERF_OPEN, &param);

Records read all start with a common { type, size } header with
DRM_I915_PERF_RECORD_SAMPLE being of most interest. Sample records
contain an extensible number of fields and it's the
DRM_I915_PERF_PROP_SAMPLE_xyz properties given when opening that
determine what's included in every sample.

No specific streams are supported yet so any attempt to open a stream
will return an error.

v2:
    use i915_gem_context_get() - Chris Wilson
v3:
    update read() interface to avoid passing state struct - Chris Wilson
    fix some rebase fallout, with i915-perf init/deinit
v4:
    s/DRM_IORW/DRM_IOW/ - Emil Velikov
Signed-off-by: default avatarRobert Bragg <robert@sixbynine.org>
Reviewed-by: default avatarMatthew Auld <matthew.auld@intel.com>
Reviewed-by: default avatarSourab Gupta <sourab.gupta@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20161107194957.3385-2-robert@sixbynine.org
parent bc1d53c6
...@@ -117,6 +117,9 @@ i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o ...@@ -117,6 +117,9 @@ i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
# virtual gpu code # virtual gpu code
i915-y += i915_vgpu.o i915-y += i915_vgpu.o
# perf code
i915-y += i915_perf.o
ifeq ($(CONFIG_DRM_I915_GVT),y) ifeq ($(CONFIG_DRM_I915_GVT),y)
i915-y += intel_gvt.o i915-y += intel_gvt.o
include $(src)/gvt/Makefile include $(src)/gvt/Makefile
......
...@@ -848,6 +848,8 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, ...@@ -848,6 +848,8 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
intel_detect_preproduction_hw(dev_priv); intel_detect_preproduction_hw(dev_priv);
i915_perf_init(dev_priv);
return 0; return 0;
err_gvt: err_gvt:
...@@ -863,6 +865,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, ...@@ -863,6 +865,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
*/ */
static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv) static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv)
{ {
i915_perf_fini(dev_priv);
i915_gem_load_cleanup(&dev_priv->drm); i915_gem_load_cleanup(&dev_priv->drm);
i915_workqueues_cleanup(dev_priv); i915_workqueues_cleanup(dev_priv);
} }
...@@ -2565,6 +2568,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = { ...@@ -2565,6 +2568,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF_DRV(I915_GEM_USERPTR, i915_gem_userptr_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_USERPTR, i915_gem_userptr_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(I915_PERF_OPEN, i915_perf_open_ioctl, DRM_RENDER_ALLOW),
}; };
static struct drm_driver driver = { static struct drm_driver driver = {
......
...@@ -1797,6 +1797,84 @@ struct intel_wm_config { ...@@ -1797,6 +1797,84 @@ struct intel_wm_config {
bool sprites_scaled; bool sprites_scaled;
}; };
struct i915_perf_stream;
struct i915_perf_stream_ops {
/* Enables the collection of HW samples, either in response to
* I915_PERF_IOCTL_ENABLE or implicitly called when stream is
* opened without I915_PERF_FLAG_DISABLED.
*/
void (*enable)(struct i915_perf_stream *stream);
/* Disables the collection of HW samples, either in response to
* I915_PERF_IOCTL_DISABLE or implicitly called before
* destroying the stream.
*/
void (*disable)(struct i915_perf_stream *stream);
/* Return: true if any i915 perf records are ready to read()
* for this stream.
*/
bool (*can_read)(struct i915_perf_stream *stream);
/* Call poll_wait, passing a wait queue that will be woken
* once there is something ready to read() for the stream
*/
void (*poll_wait)(struct i915_perf_stream *stream,
struct file *file,
poll_table *wait);
/* For handling a blocking read, wait until there is something
* to ready to read() for the stream. E.g. wait on the same
* wait queue that would be passed to poll_wait() until
* ->can_read() returns true (if its safe to call ->can_read()
* without the i915 perf lock held).
*/
int (*wait_unlocked)(struct i915_perf_stream *stream);
/* read - Copy buffered metrics as records to userspace
* @buf: the userspace, destination buffer
* @count: the number of bytes to copy, requested by userspace
* @offset: zero at the start of the read, updated as the read
* proceeds, it represents how many bytes have been
* copied so far and the buffer offset for copying the
* next record.
*
* Copy as many buffered i915 perf samples and records for
* this stream to userspace as will fit in the given buffer.
*
* Only write complete records; returning -ENOSPC if there
* isn't room for a complete record.
*
* Return any error condition that results in a short read
* such as -ENOSPC or -EFAULT, even though these may be
* squashed before returning to userspace.
*/
int (*read)(struct i915_perf_stream *stream,
char __user *buf,
size_t count,
size_t *offset);
/* Cleanup any stream specific resources.
*
* The stream will always be disabled before this is called.
*/
void (*destroy)(struct i915_perf_stream *stream);
};
struct i915_perf_stream {
struct drm_i915_private *dev_priv;
struct list_head link;
u32 sample_flags;
struct i915_gem_context *ctx;
bool enabled;
struct i915_perf_stream_ops *ops;
};
struct drm_i915_private { struct drm_i915_private {
struct drm_device drm; struct drm_device drm;
...@@ -2092,6 +2170,12 @@ struct drm_i915_private { ...@@ -2092,6 +2170,12 @@ struct drm_i915_private {
struct i915_runtime_pm pm; struct i915_runtime_pm pm;
struct {
bool initialized;
struct mutex lock;
struct list_head streams;
} perf;
/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */
struct { struct {
void (*resume)(struct drm_i915_private *); void (*resume)(struct drm_i915_private *);
...@@ -3253,6 +3337,9 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, ...@@ -3253,6 +3337,9 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, void *data, int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, void *data,
struct drm_file *file); struct drm_file *file);
int i915_perf_open_ioctl(struct drm_device *dev, void *data,
struct drm_file *file);
/* i915_gem_evict.c */ /* i915_gem_evict.c */
int __must_check i915_gem_evict_something(struct i915_address_space *vm, int __must_check i915_gem_evict_something(struct i915_address_space *vm,
u64 min_size, u64 alignment, u64 min_size, u64 alignment,
...@@ -3383,6 +3470,10 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, ...@@ -3383,6 +3470,10 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine,
u32 batch_len, u32 batch_len,
bool is_master); bool is_master);
/* i915_perf.c */
extern void i915_perf_init(struct drm_i915_private *dev_priv);
extern void i915_perf_fini(struct drm_i915_private *dev_priv);
/* i915_suspend.c */ /* i915_suspend.c */
extern int i915_save_state(struct drm_device *dev); extern int i915_save_state(struct drm_device *dev);
extern int i915_restore_state(struct drm_device *dev); extern int i915_restore_state(struct drm_device *dev);
......
This diff is collapsed.
...@@ -258,6 +258,7 @@ typedef struct _drm_i915_sarea { ...@@ -258,6 +258,7 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_GEM_USERPTR 0x33 #define DRM_I915_GEM_USERPTR 0x33
#define DRM_I915_GEM_CONTEXT_GETPARAM 0x34 #define DRM_I915_GEM_CONTEXT_GETPARAM 0x34
#define DRM_I915_GEM_CONTEXT_SETPARAM 0x35 #define DRM_I915_GEM_CONTEXT_SETPARAM 0x35
#define DRM_I915_PERF_OPEN 0x36
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
...@@ -311,6 +312,7 @@ typedef struct _drm_i915_sarea { ...@@ -311,6 +312,7 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_GEM_USERPTR DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_USERPTR, struct drm_i915_gem_userptr) #define DRM_IOCTL_I915_GEM_USERPTR DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_USERPTR, struct drm_i915_gem_userptr)
#define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param) #define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param)
#define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param) #define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param)
#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param)
/* Allow drivers to submit batchbuffers directly to hardware, relying /* Allow drivers to submit batchbuffers directly to hardware, relying
* on the security mechanisms provided by hardware. * on the security mechanisms provided by hardware.
...@@ -1228,6 +1230,71 @@ struct drm_i915_gem_context_param { ...@@ -1228,6 +1230,71 @@ struct drm_i915_gem_context_param {
__u64 value; __u64 value;
}; };
enum drm_i915_perf_property_id {
/**
* Open the stream for a specific context handle (as used with
* execbuffer2). A stream opened for a specific context this way
* won't typically require root privileges.
*/
DRM_I915_PERF_PROP_CTX_HANDLE = 1,
DRM_I915_PERF_PROP_MAX /* non-ABI */
};
struct drm_i915_perf_open_param {
__u32 flags;
#define I915_PERF_FLAG_FD_CLOEXEC (1<<0)
#define I915_PERF_FLAG_FD_NONBLOCK (1<<1)
#define I915_PERF_FLAG_DISABLED (1<<2)
/** The number of u64 (id, value) pairs */
__u32 num_properties;
/**
* Pointer to array of u64 (id, value) pairs configuring the stream
* to open.
*/
__u64 __user properties_ptr;
};
#define I915_PERF_IOCTL_ENABLE _IO('i', 0x0)
#define I915_PERF_IOCTL_DISABLE _IO('i', 0x1)
/**
* Common to all i915 perf records
*/
struct drm_i915_perf_record_header {
__u32 type;
__u16 pad;
__u16 size;
};
enum drm_i915_perf_record_type {
/**
* Samples are the work horse record type whose contents are extensible
* and defined when opening an i915 perf stream based on the given
* properties.
*
* Boolean properties following the naming convention
* DRM_I915_PERF_SAMPLE_xyz_PROP request the inclusion of 'xyz' data in
* every sample.
*
* The order of these sample properties given by userspace has no
* affect on the ordering of data within a sample. The order will be
* documented here.
*
* struct {
* struct drm_i915_perf_record_header header;
*
* TODO: itemize extensible sample data here
* };
*/
DRM_I915_PERF_RECORD_SAMPLE = 1,
DRM_I915_PERF_RECORD_MAX /* non-ABI */
};
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment