Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1235166 > unrolled thread
| Started by | Robert Bragg <robert@sixbynine.org> |
|---|---|
| First post | 2015-09-29 16:40 +0200 |
| Last post | 2015-09-30 10:40 +0200 |
| Articles | 8 — 3 participants |
Back to article view | Back to linux.kernel
[RFC 0/6] Non perf based Gen Graphics OA unit driver Robert Bragg <robert@sixbynine.org> - 2015-09-29 16:40 +0200
[RFC 6/6] drm/i915: add oa_event_min_timer_exponent sysctl Robert Bragg <robert@sixbynine.org> - 2015-09-29 16:50 +0200
[RFC 5/6] drm/i915: Add dev.i915.perf_event_paranoid sysctl option Robert Bragg <robert@sixbynine.org> - 2015-09-29 16:50 +0200
[RFC 1/6] drm/i915: Add i915 perf infrastructure Robert Bragg <robert@sixbynine.org> - 2015-09-29 16:50 +0200
[RFC 2/6] drm/i915: rename OACONTROL GEN7_OACONTROL Robert Bragg <robert@sixbynine.org> - 2015-09-29 16:50 +0200
[RFC 3/6] drm/i915: Add static '3D' Haswell OA unit config Robert Bragg <robert@sixbynine.org> - 2015-09-29 16:50 +0200
Re: [RFC 0/6] Non perf based Gen Graphics OA unit driver Zhenyu Wang <zhenyuw@linux.intel.com> - 2015-09-30 05:30 +0200
Re: [RFC 0/6] Non perf based Gen Graphics OA unit driver Chris Wilson <chris@chris-wilson.co.uk> - 2015-09-30 10:40 +0200
| From | Robert Bragg <robert@sixbynine.org> |
|---|---|
| Date | 2015-09-29 16:40 +0200 |
| Subject | [RFC 0/6] Non perf based Gen Graphics OA unit driver |
| Message-ID | <qe4ev-Oh-49@gated-at.bofh.it> |
After some recent progress enabling the Observation Architecture unit
for Gen8+, we can hopefully paint a fairly complete picture of the
requirements for supporting the unit from Haswell to Skylake and so
I'm looking again at the challenges in upstreaming this work.
Considering this, it looked like it could be worthwhile experimenting
with a non-perf based driver for the OA unit and I'm hoping to explain
why and how it went as well as request some feedback on whether we
should aim to move forward without perf.
Besides the patches forwarded here, a branch can be found for reference
here:
https://github.com/rib/linux - wip/rib/oa-without-perf branch
I created corresponding branches for Mesa and GPU Top to test this here
(same branch names):
https://github.com/rib/mesa
https://github.com/rib/gputop
Here I've only included the patches up to an initial Haswell driver,
although the wip/rib/oa-without-perf branch on github includes support
for Gen8+. Please let me know if it would be helpful to forward more.
At this point I have two drivers at feature parity; one based on perf,
one not. Technically they're very similar and the patches are split to
hopefully be quite comparable. My latest perf-based work is under
wip/rib/oa-next branches in the above repos.
So, these are the concerns I have a.t.m about upstreaming this work:
- We're bridging two complex architectures
To review this work I think it will be relevant to have a good
general familiarity with Gen graphics (e.g. thinking about the OA
unit's interaction with the command streamer and execlist
scheduling) as well as our userspace architecture and how we're
consuming OA data within Mesa to implement the
INTEL_performance_query extension.
On the flip side here, its necessary to understand the perf
userspace interface (for most this is hidden by tools so the details
aren't common knowledge) as well as the internal design, considering
that the PMU we're looking at seems to break several current design
assumptions. I can only claim a limited familiarity with perf's
design, just as a result of this work.
- Limited documentation for the OA unit:
Not unique to the OA unit but I think having a driver that extends
outside of the graphics stack, into the core perf infrastructure
probably requires more comprehensive HW + graphics stack
documentation for non drm/i915 developers. Earlier RFC discussions
were hampered somewhat by limited documentation. Improved
documentation is always desirable, but of course it can also take a
significant amount of time and effort while some key aspects
(notably the PRMs) aren't directly under my control.
- The current OA PMU driver breaks some significant design assumptions.
Existing perf pmus are used for profiling work on a cpu and we're
introducing the idea of _IS_DEVICE pmus with different security
implications, the need to fake cpu-related data (such as user/kernel
registers) to fit with perf's current design, and adding _DEVICE
records as a way to forward device-specific status records.
The OA unit writes reports of counters into a circular buffer,
without involvement from the CPU, making our PMU driver the first of
a kind.
Given the way we periodically forward data from the OA buffer to
perf's buffer, these bursts of sample writes look to perf like we're
sampling too fast and so it throttles us.
Perf supports groups of counters and allows those to be read via
transactions internally but transactions currently seem designed to
be explicitly initiated from the cpu (say in response to a userspace
read()) and while we could pull a report out of the OA buffer we
can't trigger a report from the cpu on demand.
Related to being report based; the OA counters are configured in HW
as a set while perf generally expects counter configurations to be
orthogonal. Although counters can be associated with a group leader
as they are opened, there's no clear precedent for being able to
provide group-wide configuration attributes and no obvious solution
as yet that's expected to be acceptable to upstream and meets our
userspace needs. We currently avoid using perf's grouping feature
and forward OA reports to userspace via perf's 'raw' sample field.
This suits our userspace well considering how coupled the counters
are when dealing with normalizing. It would be inconvenient to split
counters up into separate events, only to require userspace to
recombine them. For Mesa it's also convenient to be forwarded raw,
periodic reports for combining with the raw reports it captures
using MI_REPORT_PERF_COUNT commands.
Related to counter orthogonality; we can't time share the OA unit,
while event scheduling is a central design idea within perf for
allowing userspace to open + enable more events than can be
configured in HW at any one time. The OA unit is not designed to
allow re-configuration while in use. We can't reconfigure the OA
unit without loosing internal OA unit state which we can't access
explicitly to save and restore. Reconfiguring the OA unit is also
relatively slow, involving ~100 register writes. From userspace Mesa
also depends on a stable OA configuration when emitting
MI_REPORT_PERF_COUNT commands and importantly the OA unit can't be
disabled while there are outstanding MI_RPC commands lest we hang
the command streamer.
- We may be making some technical compromises a.t.m for the sake of
using perf.
perf_event_open() requires events to either relate to a pid or a
specific cpu core, while our device pmu relates to neither. Events
opened with a pid will be automatically enabled/disabled according
to the scheduling of that process - so not appropriate for us. When
an event is related to a cpu id, perf ensures pmu methods will be
invoked via an inter process interrupt on that core. To avoid
invasive changes our userspace opens OA perf events for a specific
cpu. This is workable but it means the majority of the OA driver now
runs in atomic context, including all OA report forwarding, which
isn't really necessary in our case and seems to make our locking
requirements somewhat complex as we handle the interaction with the
rest of the i915 driver.
- I'm not confident our use case benefits much from building on perf:
We aren't using existing perf based tooling with our PMU. Existing
tools typically assume you're profiling work running on a cpu, e.g.
expecting samples to be associated with instruction pointers and
user/kernel registers and aiming to represent metrics in relation
to application source code. We're forwarding fake register values
and userspace needs needs to know how to decode the raw OA reports
before anything can be reported to a user.
With the buffering done by the OA unit I don't think we currently
benefit from perf's mmapped circular buffer interface. We already
have a decoupled producer and consumer and since we have to copy out
of the OA buffer, it would work well for us to hide that copy in
a simpler read() based interface.
- Logistically it might be more practical to contain this to the
graphics stack.
It seems fair to consider that if we can't see a very compelling
benefit to building on perf, then containing this work to
drivers/gpu/drm/i915 may simplify the review process as well as
future maintenance and development.
About the initial non-perf driver:
Structurally it's very similar to the perf based implementation. The
userspace interface is inspired by perf and adds a
DRM_IOCTL_I915_PERF_OPEN ioctl that's conceptually comparable to
perf_event_open() returning an fd that userspace can poll() and read()
samples from. The fds also supports I915_PERF_IOCTL_ENABLE/DISABLE
ioctls much like perf.
When opening an event; users specify an event type (enum based a.t.m
like perf's built in event types) and a pointer to an event-specific
attributes structure which is extensible in the same way as struct
i915_perf_event_attr. Metrics can optionally be opened for a specific
GPU context (comparable to passing a pid to perf_event_open()) and the
contents of samples can be controlled via a sample_flags member as with
perf.
Userspace collects samples via read() which writes (only complete)
records to the user's given buffer. Records have a type + size
header equivalent to struct i915_perf_event_header.
Updating Mesa and GPU Top to experiment with this was straightforward
given the similarity to the perf interface. The main difference is that
it only supports forwarding metrics via read()s instead of an mmaped
circular buffer. As mentioned above, I think that suits this well, and
requires no additional copying of data. I think the userspace code has
ended up being a little simpler too.
Overall the driver currently isn't much more code than with perf (~200
lines).
Personally my gut feeling a.t.m, is that we should aim to move forward
independent from perf.
I'd really appreciate some feedback from others on this though.
Daniel and Chris; although I think it made sense at the outset to try
and use perf, in light of the above would you be open to a non-perf
based driver for the OA unit?
Peter; I wonder if you would tend to agree too that it could make sense
for us to go with our own interface here?
Kind Regards,
Robert
Robert Bragg (6):
drm/i915: Add i915 perf infrastructure
drm/i915: rename OACONTROL GEN7_OACONTROL
drm/i915: Add static '3D' Haswell OA unit config
drm/i915: Add i915 perf event for Haswell OA unit
drm/i915: Add dev.i915.perf_event_paranoid sysctl option
drm/i915: add oa_event_min_timer_exponent sysctl
drivers/gpu/drm/i915/Makefile | 4 +
drivers/gpu/drm/i915/i915_cmd_parser.c | 4 +-
drivers/gpu/drm/i915/i915_dma.c | 7 +
drivers/gpu/drm/i915/i915_drv.h | 136 ++++
drivers/gpu/drm/i915/i915_gem_context.c | 23 +-
drivers/gpu/drm/i915/i915_oa_hsw.c | 98 +++
drivers/gpu/drm/i915/i915_oa_hsw.h | 36 +
drivers/gpu/drm/i915/i915_perf.c | 1201 +++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/i915_reg.h | 340 ++++++++-
include/uapi/drm/i915_drm.h | 125 ++++
10 files changed, 1967 insertions(+), 7 deletions(-)
create mode 100644 drivers/gpu/drm/i915/i915_oa_hsw.c
create mode 100644 drivers/gpu/drm/i915/i915_oa_hsw.h
create mode 100644 drivers/gpu/drm/i915/i915_perf.c
--
2.5.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Robert Bragg <robert@sixbynine.org> |
|---|---|
| Date | 2015-09-29 16:50 +0200 |
| Subject | [RFC 6/6] drm/i915: add oa_event_min_timer_exponent sysctl |
| Message-ID | <qe4oa-ZN-25@gated-at.bofh.it> |
| In reply to | #1235166 |
The minimal sampling period is now configurable via a
dev.i915.oa_event_min_timer_exponent sysctl parameter.
Following the precedent set by perf, the default is the minimum that
won't (on its own) exceed the default kernel.perf_event_max_sample_rate
default of 100000 samples/s.
Signed-off-by: Robert Bragg <robert@sixbynine.org>
---
drivers/gpu/drm/i915/i915_perf.c | 37 ++++++++++++++++++++++++++++---------
1 file changed, 28 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index ab82857..5ef7d92 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -42,6 +42,23 @@ static u32 i915_perf_event_paranoid = true;
#define OA_EXPONENT_MAX 0x3f
+/* for sysctl proc_dointvec_minmax of i915_oa_event_min_timer_exponent */
+static int zero;
+static int oa_exponent_max = OA_EXPONENT_MAX;
+
+/* Theoretically we can program the OA unit to sample every 160ns but don't
+ * allow that by default unless root...
+ *
+ * The period is derived from the exponent as:
+ *
+ * period = 80ns * 2^(exponent + 1)
+ *
+ * Referring to perf's kernel.perf_event_max_sample_rate for a precedent
+ * (100000 by default); with an OA exponent of 6 we get a period of 10.240
+ * microseconds - just under 100000Hz
+ */
+static u32 i915_oa_event_min_timer_exponent = 6;
+
static struct i915_oa_format hsw_oa_formats[I915_OA_FORMAT_MAX] = {
[I915_OA_FORMAT_A13] = { 0, 64 },
[I915_OA_FORMAT_A29] = { 1, 128 },
@@ -674,15 +691,8 @@ static int i915_oa_event_init(struct i915_perf_event *event,
if (period_exponent > OA_EXPONENT_MAX)
return -EINVAL;
- /* Theoretically we can program the OA unit to sample every
- * 160ns but don't allow that by default unless root...
- *
- * Referring to perf's kernel.perf_event_max_sample_rate for
- * a precedent (100000 by default); with an OA exponent of
- * 6 we get a period of 10.240 microseconds -just under
- * 100000Hz
- */
- if (period_exponent < 6 && !capable(CAP_SYS_ADMIN)) {
+ if (period_exponent < i915_oa_event_min_timer_exponent &&
+ !capable(CAP_SYS_ADMIN)) {
DRM_ERROR("Sampling period too high without root privileges\n");
return -EACCES;
}
@@ -1113,6 +1123,15 @@ static struct ctl_table oa_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
+ {
+ .procname = "oa_event_min_timer_exponent",
+ .data = &i915_oa_event_min_timer_exponent,
+ .maxlen = sizeof(i915_oa_event_min_timer_exponent),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &oa_exponent_max,
+ },
{}
};
--
2.5.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Robert Bragg <robert@sixbynine.org> |
|---|---|
| Date | 2015-09-29 16:50 +0200 |
| Subject | [RFC 5/6] drm/i915: Add dev.i915.perf_event_paranoid sysctl option |
| Message-ID | <qe4ob-ZN-49@gated-at.bofh.it> |
| In reply to | #1235166 |
Consistent with the kernel.perf_event_paranoid sysctl option that can
allow non-root users to access system wide cpu metrics, this can
optionally allow non-root users to access system wide OA counter metrics
from Gen graphics hardware.
Signed-off-by: Robert Bragg <robert@sixbynine.org>
---
drivers/gpu/drm/i915/i915_perf.c | 46 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index bc1c4d1..ab82857 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -38,6 +38,8 @@
#define POLL_FREQUENCY 200
#define POLL_PERIOD max_t(u64, 10000, NSEC_PER_SEC / POLL_FREQUENCY)
+static u32 i915_perf_event_paranoid = true;
+
#define OA_EXPONENT_MAX 0x3f
static struct i915_oa_format hsw_oa_formats[I915_OA_FORMAT_MAX] = {
@@ -1016,7 +1018,13 @@ int i915_perf_open_ioctl_locked(struct drm_device *dev, void *data,
}
}
- if (!specific_ctx && !capable(CAP_SYS_ADMIN)) {
+ /* Similar to perf's kernel.perf_paranoid_cpu sysctl option
+ * we check a dev.i915.perf_event_paranoid sysctl option
+ * to determine if it's ok to access system wide OA counters
+ * without CAP_SYS_ADMIN privileges.
+ */
+ if (!specific_ctx &&
+ i915_perf_event_paranoid && !capable(CAP_SYS_ADMIN)) {
DRM_ERROR("Insufficient privileges to open perf event\n");
ret = -EACCES;
goto err_ctx;
@@ -1096,6 +1104,38 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data,
return ret;
}
+
+static struct ctl_table oa_table[] = {
+ {
+ .procname = "perf_event_paranoid",
+ .data = &i915_perf_event_paranoid,
+ .maxlen = sizeof(i915_perf_event_paranoid),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {}
+};
+
+static struct ctl_table i915_root[] = {
+ {
+ .procname = "i915",
+ .maxlen = 0,
+ .mode = 0555,
+ .child = oa_table,
+ },
+ {}
+};
+
+static struct ctl_table dev_root[] = {
+ {
+ .procname = "dev",
+ .maxlen = 0,
+ .mode = 0555,
+ .child = i915_root,
+ },
+ {}
+};
+
void i915_perf_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
@@ -1103,6 +1143,8 @@ void i915_perf_init(struct drm_device *dev)
if (!IS_HASWELL(dev))
return;
+ dev_priv->perf.sysctl_header = register_sysctl_table(dev_root);
+
hrtimer_init(&dev_priv->perf.oa.poll_check_timer,
CLOCK_MONOTONIC, HRTIMER_MODE_REL);
dev_priv->perf.oa.poll_check_timer.function = poll_check_timer_cb;
@@ -1132,6 +1174,8 @@ void i915_perf_fini(struct drm_device *dev)
if (!dev_priv->perf.initialized)
return;
+ unregister_sysctl_table(dev_priv->perf.sysctl_header);
+
dev_priv->perf.oa.ops.init_oa_buffer = NULL;
dev_priv->perf.initialized = false;
--
2.5.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Robert Bragg <robert@sixbynine.org> |
|---|---|
| Date | 2015-09-29 16:50 +0200 |
| Subject | [RFC 1/6] drm/i915: Add i915 perf infrastructure |
| Message-ID | <qe4ob-ZN-55@gated-at.bofh.it> |
| In reply to | #1235166 |
This adds a DRM_IOCTL_I915_PERF_OPEN ioctl comparable to perf_event_open
that opens a file descriptor for an event source.
Based on our initial experience aiming to use the core perf
infrastructure, this interface is inspired by perf, but focused on
exposing metrics about work running on Gen graphics instead a CPU.
One notable difference is that it doesn't support mmaping a circular
buffer of samples into userspace. The currently planned use cases
require an internal buffering that forces at least one copy of data
which can be neatly hidden in a read() based interface.
No specific event types are supported yet so perf_event_open can currently
only get as far as returning EINVAL for an unknown event type.
Signed-off-by: Robert Bragg <robert@sixbynine.org>
---
drivers/gpu/drm/i915/Makefile | 3 +
drivers/gpu/drm/i915/i915_dma.c | 7 +
drivers/gpu/drm/i915/i915_drv.h | 74 +++++++
drivers/gpu/drm/i915/i915_perf.c | 447 +++++++++++++++++++++++++++++++++++++++
include/uapi/drm/i915_drm.h | 62 ++++++
5 files changed, 593 insertions(+)
create mode 100644 drivers/gpu/drm/i915/i915_perf.c
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 44d290a..5485495 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -93,6 +93,9 @@ i915-y += dvo_ch7017.o \
# virtual gpu code
i915-y += i915_vgpu.o
+# perf code
+i915-y += i915_perf.o
+
# legacy horrors
i915-y += i915_dma.o
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 2193cc2..0424e8c 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -841,6 +841,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
mutex_init(&dev_priv->modeset_restore_lock);
mutex_init(&dev_priv->csr_lock);
+ /* Must at least be initialized before trying to pin any context
+ * which i915_perf hooks into.
+ */
+ i915_perf_init(dev);
+
intel_pm_setup(dev);
intel_display_crc_init(dev);
@@ -1090,6 +1095,7 @@ int i915_driver_unload(struct drm_device *dev)
return ret;
}
+ i915_perf_fini(dev);
intel_power_domains_fini(dev_priv);
intel_gpu_ips_teardown();
@@ -1280,6 +1286,7 @@ const struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF_DRV(I915_GEM_USERPTR, i915_gem_userptr_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_PERF_OPEN, i915_perf_open_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
};
int i915_max_ioctl = ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e0f3f05..c16c9e5 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1694,6 +1694,67 @@ struct i915_execbuffer_params {
struct drm_i915_gem_request *request;
};
+struct i915_perf_read_state {
+ int count;
+ ssize_t read;
+ char __user *buf;
+};
+
+struct i915_perf_event {
+ struct drm_i915_private *dev_priv;
+
+ struct list_head link;
+
+ u32 sample_flags;
+
+ struct intel_context *ctx;
+ bool enabled;
+
+ /* Enables the collection of HW events, either in response to
+ * I915_PERF_IOCTL_ENABLE or implicitly called when event is
+ * opened without I915_PERF_FLAG_DISABLED */
+ void (*enable)(struct i915_perf_event *event);
+
+ /* Disables the collection of HW events, either in response to
+ * I915_PERF_IOCTL_DISABLE or implicitly called before
+ * destroying the event. */
+ void (*disable)(struct i915_perf_event *event);
+
+ /* Return: true if any i915 perf records are ready to read()
+ * for this event */
+ bool (*can_read)(struct i915_perf_event *event);
+
+ /* Call poll_wait, passing a wait queue that will be woken
+ * once there is something to ready to read() for the event */
+ void (*poll_wait)(struct i915_perf_event *event,
+ struct file *file,
+ poll_table *wait);
+
+ /* For handling a blocking read, wait until there is something
+ * to ready to read() for the event. 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_event *event);
+
+ /* Copy as many buffered i915 perf samples and records for
+ * this event to userspace as will fit in the given buffer.
+ *
+ * Only write complete records.
+ *
+ * read_state->count is the length of read_state->buf
+ *
+ * Update read_state->read with the number of bytes written.
+ */
+ void (*read)(struct i915_perf_event *event,
+ struct i915_perf_read_state *read_state);
+
+ /* Cleanup any event specific resources.
+ *
+ * The event will always be disabled before this is called */
+ void (*destroy)(struct i915_perf_event *event);
+};
+
struct drm_i915_private {
struct drm_device *dev;
struct kmem_cache *objects;
@@ -1928,6 +1989,12 @@ struct drm_i915_private {
struct i915_runtime_pm pm;
+ struct {
+ bool initialized;
+ struct mutex lock;
+ struct list_head events;
+ } perf;
+
/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */
struct {
int (*execbuf_submit)(struct i915_execbuffer_params *params,
@@ -3130,6 +3197,9 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+int i915_perf_open_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file);
+
/* i915_gem_evict.c */
int __must_check i915_gem_evict_something(struct drm_device *dev,
struct i915_address_space *vm,
@@ -3239,6 +3309,10 @@ int i915_parse_cmds(struct intel_engine_cs *ring,
u32 batch_len,
bool is_master);
+/* i915_perf.c */
+extern void i915_perf_init(struct drm_device *dev);
+extern void i915_perf_fini(struct drm_device *dev);
+
/* i915_suspend.c */
extern int i915_save_state(struct drm_device *dev);
extern int i915_restore_state(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
new file mode 100644
index 0000000..477e3e6
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -0,0 +1,447 @@
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/perf_event.h>
+#include <linux/anon_inodes.h>
+#include <linux/sizes.h>
+
+#include "i915_drv.h"
+
+/**
+ * i915_perf_copy_attr() - copy specific event attributes from userspace
+ * @uattr: The u64 __user attr of drm_i915_perf_open_param
+ * @attr: Destination for copied attributes
+ * @v0_size: The smallest, version 0 size of these attributes
+ * @real_size: The latest size expected by this kernel version
+ *
+ * Specific events can define a custom attributes structure and for
+ * consistency should use this utility for reading the attributes from
+ * userspace.
+ *
+ * Note: although this verifies any unknown members beyond the expected
+ * struct size are zeroed it can't check for unused flags
+ *
+ * Return: 0 if successful, else an error code
+ */
+static int i915_perf_copy_attr(void __user *uattr,
+ void *attr,
+ u32 v0_size,
+ u32 real_size)
+{
+ u32 size;
+ int ret;
+
+ if (!access_ok(VERIFY_WRITE, uattr, v0_size))
+ return -EFAULT;
+
+ /*
+ * zero the full structure, so that a short copy will be nice.
+ */
+ memset(attr, 0, real_size);
+
+ ret = get_user(size, (u32 __user *)uattr);
+ if (ret)
+ return ret;
+
+ if (size > PAGE_SIZE) /* silly large */
+ goto err_size;
+
+ if (size < v0_size)
+ goto err_size;
+
+ /*
+ * If we're handed a bigger struct than we know of,
+ * ensure all the unknown bits are 0 - i.e. new
+ * user-space does not rely on any kernel feature
+ * extensions we dont know about yet.
+ */
+
+ if (size > real_size) {
+ unsigned char __user *addr;
+ unsigned char __user *end;
+ unsigned char val;
+
+ addr = (void __user *)uattr + sizeof(*attr);
+ end = (void __user *)uattr + size;
+
+ for (; addr < end; addr++) {
+ ret = get_user(val, addr);
+ if (ret)
+ return ret;
+ if (val)
+ goto err_size;
+ }
+ size = sizeof(*attr);
+ }
+
+ ret = copy_from_user(attr, uattr, size);
+ if (ret)
+ return -EFAULT;
+
+out:
+ return ret;
+
+err_size:
+ put_user(real_size, (u32 __user *)uattr);
+ ret = -E2BIG;
+ goto out;
+}
+
+static ssize_t i915_perf_read_locked(struct i915_perf_event *event,
+ struct file *file,
+ char __user *buf,
+ size_t count,
+ loff_t *ppos)
+{
+ struct drm_i915_private *dev_priv = event->dev_priv;
+ struct i915_perf_read_state state = { count, 0, buf };
+ int ret;
+
+ if (file->f_flags & O_NONBLOCK) {
+ if (!event->can_read(event))
+ return -EAGAIN;
+ } else {
+ mutex_unlock(&dev_priv->perf.lock);
+ ret = event->wait_unlocked(event);
+ mutex_lock(&dev_priv->perf.lock);
+
+ if (ret)
+ return ret;
+ }
+
+ event->read(event, &state);
+ if (state.read == 0)
+ return -ENOSPC;
+
+ return state.read;
+}
+
+static ssize_t i915_perf_read(struct file *file,
+ char __user *buf,
+ size_t count,
+ loff_t *ppos)
+{
+ struct i915_perf_event *event = file->private_data;
+ struct drm_i915_private *dev_priv = event->dev_priv;
+ ssize_t ret;
+
+ mutex_lock(&dev_priv->perf.lock);
+ ret = i915_perf_read_locked(event, file, buf, count, ppos);
+ mutex_unlock(&dev_priv->perf.lock);
+
+ return ret;
+}
+
+static unsigned int i915_perf_poll_locked(struct i915_perf_event *event,
+ struct file *file,
+ poll_table *wait)
+{
+ unsigned int events = 0;
+
+ event->poll_wait(event, file, wait);
+
+ if (event->can_read(event))
+ events |= POLLIN;
+
+ return events;
+}
+
+static unsigned int i915_perf_poll(struct file *file, poll_table *wait)
+{
+ struct i915_perf_event *event = file->private_data;
+ struct drm_i915_private *dev_priv = event->dev_priv;
+ int ret;
+
+ mutex_lock(&dev_priv->perf.lock);
+ ret = i915_perf_poll_locked(event, file, wait);
+ mutex_unlock(&dev_priv->perf.lock);
+
+ return ret;
+}
+
+static void i915_perf_enable_locked(struct i915_perf_event *event)
+{
+ if (event->enabled)
+ return;
+
+ /* Allow event->enable() to refer to this */
+ event->enabled = true;
+
+ if (event->enable)
+ event->enable(event);
+}
+
+static void i915_perf_disable_locked(struct i915_perf_event *event)
+{
+ if (!event->enabled)
+ return;
+
+ /* Allow event->disable() to refer to this */
+ event->enabled = false;
+
+ if (event->disable)
+ event->disable(event);
+}
+
+static long i915_perf_ioctl_locked(struct i915_perf_event *event,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ switch (cmd) {
+ case I915_PERF_IOCTL_ENABLE:
+ i915_perf_enable_locked(event);
+ return 0;
+ case I915_PERF_IOCTL_DISABLE:
+ i915_perf_disable_locked(event);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static long i915_perf_ioctl(struct file *file,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ struct i915_perf_event *event = file->private_data;
+ struct drm_i915_private *dev_priv = event->dev_priv;
+ long ret;
+
+ mutex_lock(&dev_priv->perf.lock);
+ ret = i915_perf_ioctl_locked(event, cmd, arg);
+ mutex_unlock(&dev_priv->perf.lock);
+
+ return ret;
+}
+
+static void i915_perf_destroy_locked(struct i915_perf_event *event)
+{
+ struct drm_i915_private *dev_priv = event->dev_priv;
+
+ if (event->enabled)
+ i915_perf_disable_locked(event);
+
+ if (event->destroy)
+ event->destroy(event);
+
+ list_del(&event->link);
+
+ if (event->ctx) {
+ mutex_lock(&dev_priv->dev->struct_mutex);
+ i915_gem_context_unreference(event->ctx);
+ mutex_unlock(&dev_priv->dev->struct_mutex);
+ }
+
+ kfree(event);
+}
+
+static int i915_perf_release(struct inode *inode, struct file *file)
+{
+ struct i915_perf_event *event = file->private_data;
+ struct drm_i915_private *dev_priv = event->dev_priv;
+
+ mutex_lock(&dev_priv->perf.lock);
+ i915_perf_destroy_locked(event);
+ mutex_unlock(&dev_priv->perf.lock);
+
+ return 0;
+}
+
+
+static const struct file_operations fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .release = i915_perf_release,
+ .poll = i915_perf_poll,
+ .read = i915_perf_read,
+ .unlocked_ioctl = i915_perf_ioctl,
+};
+
+static struct intel_context *
+lookup_context(struct drm_i915_private *dev_priv,
+ struct file *user_filp,
+ u32 ctx_user_handle)
+{
+ struct intel_context *ctx;
+
+ mutex_lock(&dev_priv->dev->struct_mutex);
+ list_for_each_entry(ctx, &dev_priv->context_list, link) {
+ struct drm_file *drm_file;
+
+ if (!ctx->file_priv)
+ continue;
+
+ drm_file = ctx->file_priv->file;
+
+ if (user_filp->private_data == drm_file &&
+ ctx->user_handle == ctx_user_handle) {
+ i915_gem_context_reference(ctx);
+ mutex_unlock(&dev_priv->dev->struct_mutex);
+
+ return ctx;
+ }
+ }
+ mutex_unlock(&dev_priv->dev->struct_mutex);
+
+ return NULL;
+}
+
+int i915_perf_open_ioctl_locked(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_perf_open_param *param = data;
+ u32 known_open_flags = 0;
+ u64 known_sample_flags = 0;
+ struct intel_context *specific_ctx = NULL;
+ struct i915_perf_event *event = NULL;
+ unsigned long f_flags = 0;
+ int event_fd;
+ int ret = 0;
+
+ known_open_flags = I915_PERF_FLAG_FD_CLOEXEC |
+ I915_PERF_FLAG_FD_NONBLOCK |
+ I915_PERF_FLAG_SINGLE_CONTEXT |
+ I915_PERF_FLAG_DISABLED;
+ if (param->flags & ~known_open_flags) {
+ DRM_ERROR("Unknown drm_i915_perf_open_param flag\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ known_sample_flags = I915_PERF_SAMPLE_OA_REPORT |
+ I915_PERF_SAMPLE_CTXID |
+ I915_PERF_SAMPLE_TIMESTAMP;
+ if (param->sample_flags & ~known_sample_flags) {
+ DRM_ERROR("Unknown drm_i915_perf_open_param sample_flag\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (param->flags & I915_PERF_FLAG_SINGLE_CONTEXT) {
+ u32 ctx_id = param->ctx_id;
+
+ specific_ctx = lookup_context(dev_priv, file->filp, ctx_id);
+ if (!specific_ctx) {
+ DRM_ERROR("Failed to look up context with ID %u for opening perf event\n", ctx_id);
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+
+ if (!specific_ctx && !capable(CAP_SYS_ADMIN)) {
+ DRM_ERROR("Insufficient privileges to open perf event\n");
+ ret = -EACCES;
+ goto err_ctx;
+ }
+
+ event = kzalloc(sizeof(*event), GFP_KERNEL);
+ if (!event) {
+ ret = -ENOMEM;
+ goto err_ctx;
+ }
+
+ event->sample_flags = param->sample_flags;
+ event->dev_priv = dev_priv;
+ event->ctx = specific_ctx;
+
+ switch (param->type) {
+ /* TODO: Init according to specific type */
+ default:
+ DRM_ERROR("Unknown perf event type\n");
+ ret = -EINVAL;
+ goto err_alloc;
+ }
+
+ event->ctx = specific_ctx;
+ list_add(&event->link, &dev_priv->perf.events);
+
+ if (param->flags & I915_PERF_FLAG_FD_CLOEXEC)
+ f_flags |= O_CLOEXEC;
+ if (param->flags & I915_PERF_FLAG_FD_NONBLOCK)
+ f_flags |= O_NONBLOCK;
+
+ event_fd = anon_inode_getfd("[i915_perf]", &fops, event, f_flags);
+ if (event_fd < 0) {
+ ret = event_fd;
+ goto err_open;
+ }
+
+ param->fd = event_fd;
+
+ if (!(param->flags & I915_PERF_FLAG_DISABLED))
+ i915_perf_enable_locked(event);
+
+ return 0;
+
+err_open:
+ list_del(&event->link);
+ if (event->destroy)
+ event->destroy(event);
+err_alloc:
+ kfree(event);
+err_ctx:
+ if (specific_ctx) {
+ mutex_lock(&dev_priv->dev->struct_mutex);
+ i915_gem_context_unreference(specific_ctx);
+ mutex_unlock(&dev_priv->dev->struct_mutex);
+ }
+err:
+ param->fd = -1;
+
+ return ret;
+}
+
+int i915_perf_open_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int ret;
+
+ mutex_lock(&dev_priv->perf.lock);
+ ret = i915_perf_open_ioctl_locked(dev, data, file);
+ mutex_unlock(&dev_priv->perf.lock);
+
+ return ret;
+}
+
+void i915_perf_init(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = to_i915(dev);
+
+ /* Currently no global event state to initialize */
+
+ dev_priv->perf.initialized = true;
+}
+
+void i915_perf_fini(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = to_i915(dev);
+
+ if (!dev_priv->perf.initialized)
+ return;
+
+ /* Currently nothing to clean up */
+
+ dev_priv->perf.initialized = false;
+}
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index dbd16a2..a84f71f 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -230,6 +230,7 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_GEM_USERPTR 0x33
#define DRM_I915_GEM_CONTEXT_GETPARAM 0x34
#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_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -283,6 +284,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_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_PERF_OPEN DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param)
/* Allow drivers to submit batchbuffers directly to hardware, relying
* on the security mechanisms provided by hardware.
@@ -1129,4 +1131,64 @@ struct drm_i915_gem_context_param {
__u64 value;
};
+enum drm_i915_perf_event_type {
+ I915_PERF_EVENT_TYPE_MAX /* non-ABI */
+};
+
+#define I915_PERF_FLAG_FD_CLOEXEC (1<<0)
+#define I915_PERF_FLAG_FD_NONBLOCK (1<<1)
+#define I915_PERF_FLAG_SINGLE_CONTEXT (1<<2)
+#define I915_PERF_FLAG_DISABLED (1<<3)
+
+#define I915_PERF_SAMPLE_OA_REPORT (1<<0)
+#define I915_PERF_SAMPLE_CTXID (1<<1)
+#define I915_PERF_SAMPLE_TIMESTAMP (1<<2)
+
+struct drm_i915_perf_open_param {
+ /* Such as I915_PERF_OA_EVENT */
+ __u32 type;
+
+ /* CLOEXEC, NONBLOCK, SINGLE_CONTEXT, PERIODIC... */
+ __u32 flags;
+
+ /* What to include in samples */
+ __u64 sample_flags;
+
+ /* A specific context to profile */
+ __u32 ctx_id;
+
+ /* Event specific attributes */
+ __u64 __user attr;
+
+ /* OUT */
+ __u32 fd;
+};
+
+#define I915_PERF_IOCTL_ENABLE _IO('i', 0x0)
+#define I915_PERF_IOCTL_DISABLE _IO('i', 0x1)
+
+/* Note: same as struct perf_event_header */
+struct drm_i915_perf_event_header {
+ __u32 type;
+ __u16 misc;
+ __u16 size;
+};
+
+enum drm_i915_perf_record_type {
+
+ /*
+ * struct {
+ * struct drm_i915_perf_event_header header;
+ *
+ * { u32 ctx_id; } && I915_PERF_SAMPLE_CTXID
+ * { u32 timestamp; } && I915_PERF_SAMPLE_TIMESTAMP
+ * { u32 oa_report[]; } && I915_PERF_SAMPLE_OA_REPORT
+ *
+ * };
+ */
+ DRM_I915_PERF_RECORD_SAMPLE = 1,
+
+ DRM_I915_PERF_RECORD_MAX /* non-ABI */
+};
+
#endif /* _UAPI_I915_DRM_H_ */
--
2.5.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Robert Bragg <robert@sixbynine.org> |
|---|---|
| Date | 2015-09-29 16:50 +0200 |
| Subject | [RFC 2/6] drm/i915: rename OACONTROL GEN7_OACONTROL |
| Message-ID | <qe4oc-ZN-71@gated-at.bofh.it> |
| In reply to | #1235166 |
OACONTROL changes quite a bit for gen8, with some bits split out into a
per-context OACTXCONTROL register
Signed-off-by: Robert Bragg <robert@sixbynine.org>
---
drivers/gpu/drm/i915/i915_cmd_parser.c | 4 ++--
drivers/gpu/drm/i915/i915_reg.h | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 237ff68..d769436 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -439,7 +439,7 @@ static const struct drm_i915_reg_descriptor gen7_render_regs[] = {
REG64(CL_PRIMITIVES_COUNT),
REG64(PS_INVOCATION_COUNT),
REG64(PS_DEPTH_COUNT),
- REG32(OACONTROL), /* Only allowed for LRI and SRM. See below. */
+ REG32(GEN7_OACONTROL), /* Only allowed for LRI and SRM. See below. */
REG64(MI_PREDICATE_SRC0),
REG64(MI_PREDICATE_SRC1),
REG32(GEN7_3DPRIM_END_OFFSET),
@@ -1020,7 +1020,7 @@ static bool check_cmd(const struct intel_engine_cs *ring,
* to the register. Hence, limit OACONTROL writes to
* only MI_LOAD_REGISTER_IMM commands.
*/
- if (reg_addr == OACONTROL) {
+ if (reg_addr == GEN7_OACONTROL) {
if (desc->cmd.value == MI_LOAD_REGISTER_MEM(1)) {
DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n");
return false;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 1fa0554..2e488e8 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -536,7 +536,7 @@
#define GEN7_3DPRIM_START_INSTANCE 0x243C
#define GEN7_3DPRIM_BASE_VERTEX 0x2440
-#define OACONTROL 0x2360
+#define GEN7_OACONTROL 0x2360
#define _GEN7_PIPEA_DE_LOAD_SL 0x70068
#define _GEN7_PIPEB_DE_LOAD_SL 0x71068
--
2.5.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Robert Bragg <robert@sixbynine.org> |
|---|---|
| Date | 2015-09-29 16:50 +0200 |
| Subject | [RFC 3/6] drm/i915: Add static '3D' Haswell OA unit config |
| Message-ID | <qe4oc-ZN-65@gated-at.bofh.it> |
| In reply to | #1235166 |
Adds a static OA unit, MUX + B Counter configuration for basic '3D'
metrics on Haswell. This is autogenerated from an internal XML
description of metric sets.
Signed-off-by: Robert Bragg <robert@sixbynine.org>
---
drivers/gpu/drm/i915/Makefile | 3 +-
drivers/gpu/drm/i915/i915_drv.h | 5 ++
drivers/gpu/drm/i915/i915_oa_hsw.c | 98 ++++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/i915_oa_hsw.h | 36 ++++++++++++++
4 files changed, 141 insertions(+), 1 deletion(-)
create mode 100644 drivers/gpu/drm/i915/i915_oa_hsw.c
create mode 100644 drivers/gpu/drm/i915/i915_oa_hsw.h
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 5485495..5b1c688 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -94,7 +94,8 @@ i915-y += dvo_ch7017.o \
i915-y += i915_vgpu.o
# perf code
-i915-y += i915_perf.o
+i915-y += i915_perf.o \
+ i915_oa_hsw.o
# legacy horrors
i915-y += i915_dma.o
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c16c9e5..0cb36d9 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1694,6 +1694,11 @@ struct i915_execbuffer_params {
struct drm_i915_gem_request *request;
};
+struct i915_oa_reg {
+ u32 addr;
+ u32 value;
+};
+
struct i915_perf_read_state {
int count;
ssize_t read;
diff --git a/drivers/gpu/drm/i915/i915_oa_hsw.c b/drivers/gpu/drm/i915/i915_oa_hsw.c
new file mode 100644
index 0000000..187bade
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_oa_hsw.c
@@ -0,0 +1,98 @@
+/*
+ * Autogenerated file, DO NOT EDIT manually!
+ *
+ * Copyright (c) 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "i915_drv.h"
+
+const struct i915_oa_reg i915_oa_3d_b_counter_config_hsw[] = {
+ { 0x2724, 0x00800000 },
+ { 0x2720, 0x00000000 },
+ { 0x2714, 0x00800000 },
+ { 0x2710, 0x00000000 },
+};
+const int i915_oa_3d_b_counter_config_hsw_len = 4;
+
+const struct i915_oa_reg i915_oa_3d_mux_config_hsw[] = {
+ { 0x253A4, 0x01600000 },
+ { 0x25440, 0x00100000 },
+ { 0x25128, 0x00000000 },
+ { 0x2691C, 0x00000800 },
+ { 0x26AA0, 0x01500000 },
+ { 0x26B9C, 0x00006000 },
+ { 0x2791C, 0x00000800 },
+ { 0x27AA0, 0x01500000 },
+ { 0x27B9C, 0x00006000 },
+ { 0x2641C, 0x00000400 },
+ { 0x25380, 0x00000010 },
+ { 0x2538C, 0x00000000 },
+ { 0x25384, 0x0800AAAA },
+ { 0x25400, 0x00000004 },
+ { 0x2540C, 0x06029000 },
+ { 0x25410, 0x00000002 },
+ { 0x25404, 0x5C30FFFF },
+ { 0x25100, 0x00000016 },
+ { 0x25110, 0x00000400 },
+ { 0x25104, 0x00000000 },
+ { 0x26804, 0x00001211 },
+ { 0x26884, 0x00000100 },
+ { 0x26900, 0x00000002 },
+ { 0x26908, 0x00700000 },
+ { 0x26904, 0x00000000 },
+ { 0x26984, 0x00001022 },
+ { 0x26A04, 0x00000011 },
+ { 0x26A80, 0x00000006 },
+ { 0x26A88, 0x00000C02 },
+ { 0x26A84, 0x00000000 },
+ { 0x26B04, 0x00001000 },
+ { 0x26B80, 0x00000002 },
+ { 0x26B8C, 0x00000007 },
+ { 0x26B84, 0x00000000 },
+ { 0x27804, 0x00004844 },
+ { 0x27884, 0x00000400 },
+ { 0x27900, 0x00000002 },
+ { 0x27908, 0x0E000000 },
+ { 0x27904, 0x00000000 },
+ { 0x27984, 0x00004088 },
+ { 0x27A04, 0x00000044 },
+ { 0x27A80, 0x00000006 },
+ { 0x27A88, 0x00018040 },
+ { 0x27A84, 0x00000000 },
+ { 0x27B04, 0x00004000 },
+ { 0x27B80, 0x00000002 },
+ { 0x27B8C, 0x000000E0 },
+ { 0x27B84, 0x00000000 },
+ { 0x26104, 0x00002222 },
+ { 0x26184, 0x0C006666 },
+ { 0x26284, 0x04000000 },
+ { 0x26304, 0x04000000 },
+ { 0x26400, 0x00000002 },
+ { 0x26410, 0x000000A0 },
+ { 0x26404, 0x00000000 },
+ { 0x25420, 0x04108020 },
+ { 0x25424, 0x1284A420 },
+ { 0x2541C, 0x00000000 },
+ { 0x25428, 0x00042049 },
+};
+const int i915_oa_3d_mux_config_hsw_len = 59;
diff --git a/drivers/gpu/drm/i915/i915_oa_hsw.h b/drivers/gpu/drm/i915/i915_oa_hsw.h
new file mode 100644
index 0000000..e170e4d
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_oa_hsw.h
@@ -0,0 +1,36 @@
+/*
+ * Autogenerated file, DO NOT EDIT manually!
+ *
+ * Copyright (c) 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __I915_OA_HSW_H__
+#define __I915_OA_HSW_H__
+
+/* HSW Render Metrics Basic Gen7.5 */
+extern const struct i915_oa_reg i915_oa_3d_b_counter_config_hsw[];
+extern const int i915_oa_3d_b_counter_config_hsw_len;
+extern const struct i915_oa_reg i915_oa_3d_mux_config_hsw[];
+extern const int i915_oa_3d_mux_config_hsw_len;
+
+#endif
--
2.5.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Zhenyu Wang <zhenyuw@linux.intel.com> |
|---|---|
| Date | 2015-09-30 05:30 +0200 |
| Message-ID | <qegfD-1bp-3@gated-at.bofh.it> |
| In reply to | #1235166 |
[Multipart message — attachments visible in raw view] — view raw
On 2015.09.29 15:39:03 +0100, Robert Bragg wrote: > > - Logistically it might be more practical to contain this to the > graphics stack. > > It seems fair to consider that if we can't see a very compelling > benefit to building on perf, then containing this work to > drivers/gpu/drm/i915 may simplify the review process as well as > future maintenance and development. > I think even we all initially like to go with perf but it appears later that we might need to stick this more close with i915 driver. Also think about to enable global profiling for all graphics clients, extending or enabling it within i915 specific interface seems more feasible instead of trying to create another PMU driver like previous implementation attempt to suit the need for different gfx perf data definition. Robert, thanks for send and elaborate on this. -- Open Source Technology Center, Intel ltd. $gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827
[toc] | [prev] | [next] | [standalone]
| From | Chris Wilson <chris@chris-wilson.co.uk> |
|---|---|
| Date | 2015-09-30 10:40 +0200 |
| Message-ID | <qel5E-85q-17@gated-at.bofh.it> |
| In reply to | #1235166 |
On Tue, Sep 29, 2015 at 03:39:03PM +0100, Robert Bragg wrote: > Updating Mesa and GPU Top to experiment with this was straightforward > given the similarity to the perf interface. The main difference is that > it only supports forwarding metrics via read()s instead of an mmaped > circular buffer. As mentioned above, I think that suits this well, and > requires no additional copying of data. I think the userspace code has > ended up being a little simpler too. Did you try updating the existing perf based overlay? > Overall the driver currently isn't much more code than with perf (~200 > lines). > > Personally my gut feeling a.t.m, is that we should aim to move forward > independent from perf. > > I'd really appreciate some feedback from others on this though. > > Daniel and Chris; although I think it made sense at the outset to try > and use perf, in light of the above would you be open to a non-perf > based driver for the OA unit? No. I strongly dislike that they will be multiple incompatibile perf interfaces and strongly like the coupling with other profiling that comes with perf - i.e. we very much want to simultaneously sample CPU and GPU workloads along with other devices, that information is much more useful to me for the purposes of scheduling work and maximising concurrency than optimising shaders. -Chris -- Chris Wilson, Intel Open Source Technology Centre -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web