115 lines
		
	
	
	
		
			2.6 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			115 lines
		
	
	
	
		
			2.6 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  * Copyright 2014, Michael Ellerman, IBM Corp. | ||
|  |  * Licensed under GPLv2. | ||
|  |  */ | ||
|  | 
 | ||
|  | #define _GNU_SOURCE
 | ||
|  | 
 | ||
|  | #include <elf.h>
 | ||
|  | #include <limits.h>
 | ||
|  | #include <stdio.h>
 | ||
|  | #include <stdbool.h>
 | ||
|  | #include <string.h>
 | ||
|  | #include <sys/prctl.h>
 | ||
|  | 
 | ||
|  | #include "event.h"
 | ||
|  | #include "lib.h"
 | ||
|  | #include "utils.h"
 | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Test that per-event excludes work. | ||
|  |  */ | ||
|  | 
 | ||
|  | static int per_event_excludes(void) | ||
|  | { | ||
|  | 	struct event *e, events[4]; | ||
|  | 	char *platform; | ||
|  | 	int i; | ||
|  | 
 | ||
|  | 	platform = (char *)get_auxv_entry(AT_BASE_PLATFORM); | ||
|  | 	FAIL_IF(!platform); | ||
|  | 	SKIP_IF(strcmp(platform, "power8") != 0); | ||
|  | 
 | ||
|  | 	/*
 | ||
|  | 	 * We need to create the events disabled, otherwise the running/enabled | ||
|  | 	 * counts don't match up. | ||
|  | 	 */ | ||
|  | 	e = &events[0]; | ||
|  | 	event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS, | ||
|  | 			PERF_TYPE_HARDWARE, "instructions"); | ||
|  | 	e->attr.disabled = 1; | ||
|  | 
 | ||
|  | 	e = &events[1]; | ||
|  | 	event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS, | ||
|  | 			PERF_TYPE_HARDWARE, "instructions(k)"); | ||
|  | 	e->attr.disabled = 1; | ||
|  | 	e->attr.exclude_user = 1; | ||
|  | 	e->attr.exclude_hv = 1; | ||
|  | 
 | ||
|  | 	e = &events[2]; | ||
|  | 	event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS, | ||
|  | 			PERF_TYPE_HARDWARE, "instructions(h)"); | ||
|  | 	e->attr.disabled = 1; | ||
|  | 	e->attr.exclude_user = 1; | ||
|  | 	e->attr.exclude_kernel = 1; | ||
|  | 
 | ||
|  | 	e = &events[3]; | ||
|  | 	event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS, | ||
|  | 			PERF_TYPE_HARDWARE, "instructions(u)"); | ||
|  | 	e->attr.disabled = 1; | ||
|  | 	e->attr.exclude_hv = 1; | ||
|  | 	e->attr.exclude_kernel = 1; | ||
|  | 
 | ||
|  | 	FAIL_IF(event_open(&events[0])); | ||
|  | 
 | ||
|  | 	/*
 | ||
|  | 	 * The open here will fail if we don't have per event exclude support, | ||
|  | 	 * because the second event has an incompatible set of exclude settings | ||
|  | 	 * and we're asking for the events to be in a group. | ||
|  | 	 */ | ||
|  | 	for (i = 1; i < 4; i++) | ||
|  | 		FAIL_IF(event_open_with_group(&events[i], events[0].fd)); | ||
|  | 
 | ||
|  | 	/*
 | ||
|  | 	 * Even though the above will fail without per-event excludes we keep | ||
|  | 	 * testing in order to be thorough. | ||
|  | 	 */ | ||
|  | 	prctl(PR_TASK_PERF_EVENTS_ENABLE); | ||
|  | 
 | ||
|  | 	/* Spin for a while */ | ||
|  | 	for (i = 0; i < INT_MAX; i++) | ||
|  | 		asm volatile("" : : : "memory"); | ||
|  | 
 | ||
|  | 	prctl(PR_TASK_PERF_EVENTS_DISABLE); | ||
|  | 
 | ||
|  | 	for (i = 0; i < 4; i++) { | ||
|  | 		FAIL_IF(event_read(&events[i])); | ||
|  | 		event_report(&events[i]); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/*
 | ||
|  | 	 * We should see that all events have enabled == running. That | ||
|  | 	 * shows that they were all on the PMU at once. | ||
|  | 	 */ | ||
|  | 	for (i = 0; i < 4; i++) | ||
|  | 		FAIL_IF(events[i].result.running != events[i].result.enabled); | ||
|  | 
 | ||
|  | 	/*
 | ||
|  | 	 * We can also check that the result for instructions is >= all the | ||
|  | 	 * other counts. That's because it is counting all instructions while | ||
|  | 	 * the others are counting a subset. | ||
|  | 	 */ | ||
|  | 	for (i = 1; i < 4; i++) | ||
|  | 		FAIL_IF(events[0].result.value < events[i].result.value); | ||
|  | 
 | ||
|  | 	for (i = 0; i < 4; i++) | ||
|  | 		event_close(&events[i]); | ||
|  | 
 | ||
|  | 	return 0; | ||
|  | } | ||
|  | 
 | ||
|  | int main(void) | ||
|  | { | ||
|  | 	return test_harness(per_event_excludes, "per_event_excludes"); | ||
|  | } |