mirror of
				https://github.com/tiagovignatti/intel-gpu-tools.git
				synced 2025-11-04 03:58:27 +00:00 
			
		
		
		
	overlay: Read power from perf_events
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
		
							parent
							
								
									6ec1d2c0ae
								
							
						
					
					
						commit
						1c3fd70357
					
				@ -29,6 +29,8 @@ intel_gpu_overlay_SOURCES = \
 | 
				
			|||||||
	igfx.c \
 | 
						igfx.c \
 | 
				
			||||||
	overlay.h \
 | 
						overlay.h \
 | 
				
			||||||
	overlay.c \
 | 
						overlay.c \
 | 
				
			||||||
 | 
						perf.h \
 | 
				
			||||||
 | 
						perf.c \
 | 
				
			||||||
	power.h \
 | 
						power.h \
 | 
				
			||||||
	power.c \
 | 
						power.c \
 | 
				
			||||||
	rc6.h \
 | 
						rc6.h \
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <linux/perf_event.h>
 | 
					 | 
				
			||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
#include <sys/mman.h>
 | 
					#include <sys/mman.h>
 | 
				
			||||||
#include <sys/ioctl.h>
 | 
					#include <sys/ioctl.h>
 | 
				
			||||||
@ -35,6 +34,7 @@
 | 
				
			|||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "perf.h"
 | 
				
			||||||
#include "gpu-perf.h"
 | 
					#include "gpu-perf.h"
 | 
				
			||||||
#include "debugfs.h"
 | 
					#include "debugfs.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -59,27 +59,6 @@ struct sample_event {
 | 
				
			|||||||
	uint32_t raw[0];
 | 
						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)
 | 
					static uint64_t tracepoint_id(const char *sys, const char *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char buf[1024];
 | 
						char buf[1024];
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,6 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/perf_event.h>
 | 
					 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
@ -31,6 +30,7 @@
 | 
				
			|||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "perf.h"
 | 
				
			||||||
#include "igfx.h"
 | 
					#include "igfx.h"
 | 
				
			||||||
#include "gpu-top.h"
 | 
					#include "gpu-top.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -46,45 +46,6 @@
 | 
				
			|||||||
#define I915_PERF_RING_WAIT(n) (__I915_PERF_RING(n) + 1)
 | 
					#define I915_PERF_RING_WAIT(n) (__I915_PERF_RING(n) + 1)
 | 
				
			||||||
#define I915_PERF_RING_SEMA(n) (__I915_PERF_RING(n) + 2)
 | 
					#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)
 | 
					static int perf_i915_open(int config, int group)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct perf_event_attr attr;
 | 
						struct perf_event_attr attr;
 | 
				
			||||||
@ -106,9 +67,9 @@ static int perf_i915_open(int config, int group)
 | 
				
			|||||||
static int perf_init(struct gpu_top *gt)
 | 
					static int perf_init(struct gpu_top *gt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *names[] = {
 | 
						const char *names[] = {
 | 
				
			||||||
		"render",
 | 
							"RCS",
 | 
				
			||||||
		"bitstream",
 | 
							"VCS",
 | 
				
			||||||
		"bliter",
 | 
							"BCS",
 | 
				
			||||||
		NULL,
 | 
							NULL,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	int n;
 | 
						int n;
 | 
				
			||||||
 | 
				
			|||||||
@ -742,7 +742,7 @@ int main(int argc, char **argv)
 | 
				
			|||||||
	config_init(&config);
 | 
						config_init(&config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	opterr = 0;
 | 
						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) {
 | 
							switch (i) {
 | 
				
			||||||
		case 'c':
 | 
							case 'c':
 | 
				
			||||||
			config_parse_string(&config, optarg);
 | 
								config_parse_string(&config, optarg);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										26
									
								
								overlay/perf.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								overlay/perf.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					#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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										60
									
								
								overlay/perf.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								overlay/perf.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					#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 */
 | 
				
			||||||
@ -22,6 +22,7 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
@ -30,11 +31,27 @@
 | 
				
			|||||||
#include <time.h>
 | 
					#include <time.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "perf.h"
 | 
				
			||||||
#include "power.h"
 | 
					#include "power.h"
 | 
				
			||||||
#include "debugfs.h"
 | 
					#include "debugfs.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* XXX Is this exposed through RAPL? */
 | 
					/* 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)
 | 
					int power_init(struct power *power)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char buf[4096];
 | 
						char buf[4096];
 | 
				
			||||||
@ -42,6 +59,10 @@ int power_init(struct power *power)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	memset(power, 0, sizeof(*power));
 | 
						memset(power, 0, sizeof(*power));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						power->fd = perf_open();
 | 
				
			||||||
 | 
						if (power->fd != -1)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sprintf(buf, "%s/i915_energy_uJ", debugfs_dri_path);
 | 
						sprintf(buf, "%s/i915_energy_uJ", debugfs_dri_path);
 | 
				
			||||||
	fd = open(buf, 0);
 | 
						fd = open(buf, 0);
 | 
				
			||||||
	if (fd < 0)
 | 
						if (fd < 0)
 | 
				
			||||||
@ -100,17 +121,25 @@ int power_update(struct power *power)
 | 
				
			|||||||
	if (power->error)
 | 
						if (power->error)
 | 
				
			||||||
		return power->error;
 | 
							return power->error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s->energy = file_to_u64("i915_energy_uJ");
 | 
						if (power->fd != -1) {
 | 
				
			||||||
	s->timestamp = clock_ms_to_u64();
 | 
							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)
 | 
						if (power->count == 1)
 | 
				
			||||||
		return EAGAIN;
 | 
							return EAGAIN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	d_time = s->timestamp - d->timestamp;
 | 
						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->power_mW = (s->energy - d->energy) / d_time;
 | 
				
			||||||
	power->new_sample = 1;
 | 
						power->new_sample = 1;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
				
			|||||||
@ -33,6 +33,7 @@ struct power {
 | 
				
			|||||||
		uint64_t timestamp;
 | 
							uint64_t timestamp;
 | 
				
			||||||
	} stat[2];
 | 
						} stat[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int fd;
 | 
				
			||||||
	int error;
 | 
						int error;
 | 
				
			||||||
	int count;
 | 
						int count;
 | 
				
			||||||
	int new_sample;
 | 
						int new_sample;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user