igfx.c \
overlay.h \
overlay.c \
+ perf.h \
+ perf.c \
power.h \
power.c \
rc6.h \
#include <stdint.h>
#include <stdbool.h>
-#include <linux/perf_event.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
+#include "perf.h"
#include "gpu-perf.h"
#include "debugfs.h"
uint32_t raw[0];
};
-static int
-perf_event_open(struct perf_event_attr *attr,
- pid_t pid,
- int cpu,
- int group_fd,
- unsigned long flags)
-{
-#ifndef __NR_perf_event_open
-#if defined(__i386__)
-#define __NR_perf_event_open 336
-#elif defined(__x86_64__)
-#define __NR_perf_event_open 298
-#else
-#define __NR_perf_event_open 0
-#endif
-#endif
-
- attr->size = sizeof(*attr);
- return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
-}
-
static uint64_t tracepoint_id(const char *sys, const char *name)
{
char buf[1024];
*
*/
-#include <linux/perf_event.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
+#include "perf.h"
#include "igfx.h"
#include "gpu-top.h"
#define I915_PERF_RING_WAIT(n) (__I915_PERF_RING(n) + 1)
#define I915_PERF_RING_SEMA(n) (__I915_PERF_RING(n) + 2)
-static int
-perf_event_open(struct perf_event_attr *attr,
- pid_t pid,
- int cpu,
- int group_fd,
- unsigned long flags)
-{
-#ifndef __NR_perf_event_open
-#if defined(__i386__)
-#define __NR_perf_event_open 336
-#elif defined(__x86_64__)
-#define __NR_perf_event_open 298
-#else
-#define __NR_perf_event_open 0
-#endif
-#endif
- attr->size = sizeof(*attr);
- return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
-}
-
-static uint64_t i915_type_id(void)
-{
- char buf[1024];
- int fd, n;
-
- fd = open("/sys/bus/event_source/devices/i915/type", 0);
- if (fd < 0) {
- n = -1;
- } else {
- n = read(fd, buf, sizeof(buf)-1);
- close(fd);
- }
- if (n < 0)
- return 0;
-
- buf[n] = '\0';
- return strtoull(buf, 0, 0);
-}
-
static int perf_i915_open(int config, int group)
{
struct perf_event_attr attr;
static int perf_init(struct gpu_top *gt)
{
const char *names[] = {
- "render",
- "bitstream",
- "bliter",
+ "RCS",
+ "VCS",
+ "BCS",
NULL,
};
int n;
config_init(&config);
opterr = 0;
- while ((i = getopt_long(argc, argv, "c:f:", long_options, &index)) != -1) {
+ while ((i = getopt_long(argc, argv, "c:f", long_options, &index)) != -1) {
switch (i) {
case 'c':
config_parse_string(&config, optarg);
--- /dev/null
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "perf.h"
+
+uint64_t i915_type_id(void)
+{
+ char buf[1024];
+ int fd, n;
+
+ fd = open("/sys/bus/event_source/devices/i915/type", 0);
+ if (fd < 0) {
+ n = -1;
+ } else {
+ n = read(fd, buf, sizeof(buf)-1);
+ close(fd);
+ }
+ if (n < 0)
+ return 0;
+
+ buf[n] = '\0';
+ return strtoull(buf, 0, 0);
+}
+
--- /dev/null
+#ifndef I915_PERF_H
+#define I915_PERF_H
+
+#include <linux/perf_event.h>
+
+#define I915_SAMPLE_BUSY 0
+#define I915_SAMPLE_WAIT 1
+#define I915_SAMPLE_SEMA 2
+
+#define I915_SAMPLE_RCS 0
+#define I915_SAMPLE_VCS 1
+#define I915_SAMPLE_BCS 2
+#define I915_SAMPLE_VECS 3
+
+#define __I915_PERF_COUNT(ring, id) ((ring) << 4 | (id))
+
+#define I915_PERF_COUNT_RCS_BUSY __I915_PERF_COUNT(I915_SAMPLE_RCS, I915_SAMPLE_BUSY)
+#define I915_PERF_COUNT_RCS_WAIT __I915_PERF_COUNT(I915_SAMPLE_RCS, I915_SAMPLE_WAIT)
+#define I915_PERF_COUNT_RCS_SEMA __I915_PERF_COUNT(I915_SAMPLE_RCS, I915_SAMPLE_SEMA)
+
+#define I915_PERF_COUNT_VCS_BUSY __I915_PERF_COUNT(I915_SAMPLE_VCS, I915_SAMPLE_BUSY)
+#define I915_PERF_COUNT_VCS_WAIT __I915_PERF_COUNT(I915_SAMPLE_VCS, I915_SAMPLE_WAIT)
+#define I915_PERF_COUNT_VCS_SEMA __I915_PERF_COUNT(I915_SAMPLE_VCS, I915_SAMPLE_SEMA)
+
+#define I915_PERF_COUNT_BCS_BUSY __I915_PERF_COUNT(I915_SAMPLE_BCS, I915_SAMPLE_BUSY)
+#define I915_PERF_COUNT_BCS_WAIT __I915_PERF_COUNT(I915_SAMPLE_BCS, I915_SAMPLE_WAIT)
+#define I915_PERF_COUNT_BCS_SEMA __I915_PERF_COUNT(I915_SAMPLE_BCS, I915_SAMPLE_SEMA)
+
+#define I915_PERF_COUNT_VECS_BUSY __I915_PERF_COUNT(I915_SAMPLE_VECS, I915_SAMPLE_BUSY)
+#define I915_PERF_COUNT_VECS_WAIT __I915_PERF_COUNT(I915_SAMPLE_VECS, I915_SAMPLE_WAIT)
+#define I915_PERF_COUNT_VECS_SEMA __I915_PERF_COUNT(I915_SAMPLE_VECS, I915_SAMPLE_SEMA)
+
+#define I915_PERF_ACTUAL_FREQUENCY 32
+#define I915_PERF_REQUESTED_FREQUENCY 33
+#define I915_PERF_ENERGY 34
+#define I915_PERF_INTERRUPTS 35
+
+static inline int
+perf_event_open(struct perf_event_attr *attr,
+ pid_t pid,
+ int cpu,
+ int group_fd,
+ unsigned long flags)
+{
+#ifndef __NR_perf_event_open
+#if defined(__i386__)
+#define __NR_perf_event_open 336
+#elif defined(__x86_64__)
+#define __NR_perf_event_open 298
+#else
+#define __NR_perf_event_open 0
+#endif
+#endif
+ attr->size = sizeof(*attr);
+ return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
+}
+
+uint64_t i915_type_id(void);
+
+#endif /* I915_PERF_H */
*
*/
+#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <errno.h>
+#include "perf.h"
#include "power.h"
#include "debugfs.h"
/* XXX Is this exposed through RAPL? */
+static int perf_open(void)
+{
+ struct perf_event_attr attr;
+
+ memset(&attr, 0, sizeof (attr));
+
+ attr.type = i915_type_id();
+ if (attr.type == 0)
+ return -ENOENT;
+ attr.config = I915_PERF_ENERGY;
+
+ attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED;
+ return perf_event_open(&attr, -1, 0, -1, 0);
+}
+
int power_init(struct power *power)
{
char buf[4096];
memset(power, 0, sizeof(*power));
+ power->fd = perf_open();
+ if (power->fd != -1)
+ return 0;
+
sprintf(buf, "%s/i915_energy_uJ", debugfs_dri_path);
fd = open(buf, 0);
if (fd < 0)
if (power->error)
return power->error;
- s->energy = file_to_u64("i915_energy_uJ");
- s->timestamp = clock_ms_to_u64();
+ if (power->fd != -1) {
+ uint64_t data[2];
+ int len;
+
+ len = read(power->fd, data, sizeof(data));
+ if (len < 0)
+ return power->error = errno;
+
+ s->energy = data[0];
+ s->timestamp = data[1] / (1000*1000);
+ } else {
+ s->energy = file_to_u64("i915_energy_uJ");
+ s->timestamp = clock_ms_to_u64();
+ }
+
if (power->count == 1)
return EAGAIN;
d_time = s->timestamp - d->timestamp;
- if (d_time < 900) { /* HW sample rate seems to be stable ~1Hz */
- power->count--;
- return power->count <= 1 ? EAGAIN : 0;
- }
-
power->power_mW = (s->energy - d->energy) / d_time;
power->new_sample = 1;
return 0;
uint64_t timestamp;
} stat[2];
+ int fd;
int error;
int count;
int new_sample;