diff options
Diffstat (limited to 'tools/testing/selftests')
185 files changed, 8493 insertions, 50 deletions
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 9f3eae29090..e66e710cc59 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -9,6 +9,8 @@ TARGETS += ptrace  TARGETS += timers  TARGETS += vm  TARGETS += powerpc +TARGETS += user +TARGETS += sysctl  all:  	for TARGET in $(TARGETS); do \ diff --git a/tools/testing/selftests/cpu-hotplug/Makefile b/tools/testing/selftests/cpu-hotplug/Makefile index ae5faf9aade..790c23a9db4 100644 --- a/tools/testing/selftests/cpu-hotplug/Makefile +++ b/tools/testing/selftests/cpu-hotplug/Makefile @@ -1,6 +1,6 @@  all:  run_tests: -	@/bin/sh ./on-off-test.sh || echo "cpu-hotplug selftests: [FAIL]" +	@/bin/bash ./on-off-test.sh || echo "cpu-hotplug selftests: [FAIL]"  clean: diff --git a/tools/testing/selftests/ipc/msgque.c b/tools/testing/selftests/ipc/msgque.c index d66418237d2..552f0810bff 100644 --- a/tools/testing/selftests/ipc/msgque.c +++ b/tools/testing/selftests/ipc/msgque.c @@ -193,6 +193,11 @@ int main(int argc, char **argv)  	int msg, pid, err;  	struct msgque_data msgque; +	if (getuid() != 0) { +		printf("Please run the test as root - Exiting.\n"); +		exit(1); +	} +  	msgque.key = ftok(argv[0], 822155650);  	if (msgque.key == -1) {  		printf("Can't make key\n"); @@ -201,6 +206,7 @@ int main(int argc, char **argv)  	msgque.msq_id = msgget(msgque.key, IPC_CREAT | IPC_EXCL | 0666);  	if (msgque.msq_id == -1) { +		err = -errno;  		printf("Can't create queue\n");  		goto err_out;  	} diff --git a/tools/testing/selftests/memory-hotplug/Makefile b/tools/testing/selftests/memory-hotplug/Makefile index 350bfeda3aa..058c76f5d10 100644 --- a/tools/testing/selftests/memory-hotplug/Makefile +++ b/tools/testing/selftests/memory-hotplug/Makefile @@ -1,6 +1,6 @@  all:  run_tests: -	@/bin/sh ./on-off-test.sh || echo "memory-hotplug selftests: [FAIL]" +	@/bin/bash ./on-off-test.sh || echo "memory-hotplug selftests: [FAIL]"  clean: diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index 750512ba2c8..c7493b8f9b0 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -14,6 +14,12 @@ all: $(NET_PROGS)  run_tests: all  	@/bin/sh ./run_netsocktests || echo "sockettests: [FAIL]"  	@/bin/sh ./run_afpackettests || echo "afpackettests: [FAIL]" - +	@if /sbin/modprobe test_bpf ; then \ +		/sbin/rmmod test_bpf; \ +		echo "test_bpf: ok"; \ +	else \ +		echo "test_bpf: [FAIL]"; \ +		exit 1; \ +	fi  clean:  	$(RM) $(NET_PROGS) diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile index bd24ae5aaea..54833a791a4 100644 --- a/tools/testing/selftests/powerpc/Makefile +++ b/tools/testing/selftests/powerpc/Makefile @@ -13,7 +13,7 @@ CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CUR  export CC CFLAGS -TARGETS = pmu +TARGETS = pmu copyloops mm tm  endif diff --git a/tools/testing/selftests/powerpc/copyloops/Makefile b/tools/testing/selftests/powerpc/copyloops/Makefile new file mode 100644 index 00000000000..6f2d3be227f --- /dev/null +++ b/tools/testing/selftests/powerpc/copyloops/Makefile @@ -0,0 +1,29 @@ +# The loops are all 64-bit code +CFLAGS += -m64 +CFLAGS += -I$(CURDIR) +CFLAGS += -D SELFTEST + +# Use our CFLAGS for the implicit .S rule +ASFLAGS = $(CFLAGS) + +PROGS := copyuser_64 copyuser_power7 memcpy_64 memcpy_power7 +EXTRA_SOURCES := validate.c ../harness.c + +all: $(PROGS) + +copyuser_64:     CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_base +copyuser_power7: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_power7 +memcpy_64:       CPPFLAGS += -D COPY_LOOP=test_memcpy +memcpy_power7:   CPPFLAGS += -D COPY_LOOP=test_memcpy_power7 + +$(PROGS): $(EXTRA_SOURCES) + +run_tests: all +	@-for PROG in $(PROGS); do \ +		./$$PROG; \ +	done; + +clean: +	rm -f $(PROGS) *.o + +.PHONY: all run_tests clean diff --git a/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h b/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h new file mode 100644 index 00000000000..d1dc3742551 --- /dev/null +++ b/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h @@ -0,0 +1,89 @@ +#include <ppc-asm.h> + +#define CONFIG_ALTIVEC + +#define r1	1 + +#define vr0     0 +#define vr1     1 +#define vr2     2 +#define vr3     3 +#define vr4     4 +#define vr5     5 +#define vr6     6 +#define vr7     7 +#define vr8     8 +#define vr9     9 +#define vr10    10 +#define vr11    11 +#define vr12    12 +#define vr13    13 +#define vr14    14 +#define vr15    15 +#define vr16    16 +#define vr17    17 +#define vr18    18 +#define vr19    19 +#define vr20    20 +#define vr21    21 +#define vr22    22 +#define vr23    23 +#define vr24    24 +#define vr25    25 +#define vr26    26 +#define vr27    27 +#define vr28    28 +#define vr29    29 +#define vr30    30 +#define vr31    31 + +#define R14 r14 +#define R15 r15 +#define R16 r16 +#define R17 r17 +#define R18 r18 +#define R19 r19 +#define R20 r20 +#define R21 r21 +#define R22 r22 +#define R29 r29 +#define R30 r30 +#define R31 r31 + +#define STACKFRAMESIZE	256 +#define STK_REG(i)	(112 + ((i)-14)*8) + +#define _GLOBAL(A) FUNC_START(test_ ## A) +#define _GLOBAL_TOC(A) _GLOBAL(A) + +#define PPC_MTOCRF(A, B)	mtocrf A, B + +FUNC_START(enter_vmx_usercopy) +	li	r3,1 +	blr + +FUNC_START(exit_vmx_usercopy) +	li	r3,0 +	blr + +FUNC_START(enter_vmx_copy) +	li	r3,1 +	blr + +FUNC_START(exit_vmx_copy) +	blr + +FUNC_START(memcpy_power7) +	blr + +FUNC_START(__copy_tofrom_user_power7) +	blr + +FUNC_START(__copy_tofrom_user_base) +	blr + +#define BEGIN_FTR_SECTION +#define FTR_SECTION_ELSE +#define ALT_FTR_SECTION_END_IFCLR(x) +#define ALT_FTR_SECTION_END(x, y) +#define END_FTR_SECTION_IFCLR(x) diff --git a/tools/testing/selftests/powerpc/copyloops/asm/processor.h b/tools/testing/selftests/powerpc/copyloops/asm/processor.h new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/tools/testing/selftests/powerpc/copyloops/asm/processor.h diff --git a/tools/testing/selftests/powerpc/copyloops/copyuser_64.S b/tools/testing/selftests/powerpc/copyloops/copyuser_64.S new file mode 120000 index 00000000000..f1c418a2521 --- /dev/null +++ b/tools/testing/selftests/powerpc/copyloops/copyuser_64.S @@ -0,0 +1 @@ +../../../../../arch/powerpc/lib/copyuser_64.S
\ No newline at end of file diff --git a/tools/testing/selftests/powerpc/copyloops/copyuser_power7.S b/tools/testing/selftests/powerpc/copyloops/copyuser_power7.S new file mode 120000 index 00000000000..47868959829 --- /dev/null +++ b/tools/testing/selftests/powerpc/copyloops/copyuser_power7.S @@ -0,0 +1 @@ +../../../../../arch/powerpc/lib/copyuser_power7.S
\ No newline at end of file diff --git a/tools/testing/selftests/powerpc/copyloops/memcpy_64.S b/tools/testing/selftests/powerpc/copyloops/memcpy_64.S new file mode 120000 index 00000000000..cce33fb6f9d --- /dev/null +++ b/tools/testing/selftests/powerpc/copyloops/memcpy_64.S @@ -0,0 +1 @@ +../../../../../arch/powerpc/lib/memcpy_64.S
\ No newline at end of file diff --git a/tools/testing/selftests/powerpc/copyloops/memcpy_power7.S b/tools/testing/selftests/powerpc/copyloops/memcpy_power7.S new file mode 120000 index 00000000000..0d6fbfaf3d5 --- /dev/null +++ b/tools/testing/selftests/powerpc/copyloops/memcpy_power7.S @@ -0,0 +1 @@ +../../../../../arch/powerpc/lib/memcpy_power7.S
\ No newline at end of file diff --git a/tools/testing/selftests/powerpc/copyloops/validate.c b/tools/testing/selftests/powerpc/copyloops/validate.c new file mode 100644 index 00000000000..1750ff57ee5 --- /dev/null +++ b/tools/testing/selftests/powerpc/copyloops/validate.c @@ -0,0 +1,99 @@ +#include <malloc.h> +#include <string.h> +#include <stdlib.h> +#include <stdbool.h> + +#include "../utils.h" + +#define MAX_LEN 8192 +#define MAX_OFFSET 16 +#define MIN_REDZONE 128 +#define BUFLEN (MAX_LEN+MAX_OFFSET+2*MIN_REDZONE) +#define POISON 0xa5 + +unsigned long COPY_LOOP(void *to, const void *from, unsigned long size); + +static void do_one(char *src, char *dst, unsigned long src_off, +		   unsigned long dst_off, unsigned long len, void *redzone, +		   void *fill) +{ +	char *srcp, *dstp; +	unsigned long ret; +	unsigned long i; + +	srcp = src + MIN_REDZONE + src_off; +	dstp = dst + MIN_REDZONE + dst_off; + +	memset(src, POISON, BUFLEN); +	memset(dst, POISON, BUFLEN); +	memcpy(srcp, fill, len); + +	ret = COPY_LOOP(dstp, srcp, len); +	if (ret && ret != (unsigned long)dstp) { +		printf("(%p,%p,%ld) returned %ld\n", dstp, srcp, len, ret); +		abort(); +	} + +	if (memcmp(dstp, srcp, len)) { +		printf("(%p,%p,%ld) miscompare\n", dstp, srcp, len); +		printf("src: "); +		for (i = 0; i < len; i++) +			printf("%02x ", srcp[i]); +		printf("\ndst: "); +		for (i = 0; i < len; i++) +			printf("%02x ", dstp[i]); +		printf("\n"); +		abort(); +	} + +	if (memcmp(dst, redzone, dstp - dst)) { +		printf("(%p,%p,%ld) redzone before corrupted\n", +		       dstp, srcp, len); +		abort(); +	} + +	if (memcmp(dstp+len, redzone, dst+BUFLEN-(dstp+len))) { +		printf("(%p,%p,%ld) redzone after corrupted\n", +		       dstp, srcp, len); +		abort(); +	} +} + +int test_copy_loop(void) +{ +	char *src, *dst, *redzone, *fill; +	unsigned long len, src_off, dst_off; +	unsigned long i; + +	src = memalign(BUFLEN, BUFLEN); +	dst = memalign(BUFLEN, BUFLEN); +	redzone = malloc(BUFLEN); +	fill = malloc(BUFLEN); + +	if (!src || !dst || !redzone || !fill) { +		fprintf(stderr, "malloc failed\n"); +		exit(1); +	} + +	memset(redzone, POISON, BUFLEN); + +	/* Fill with sequential bytes */ +	for (i = 0; i < BUFLEN; i++) +		fill[i] = i & 0xff; + +	for (len = 1; len < MAX_LEN; len++) { +		for (src_off = 0; src_off < MAX_OFFSET; src_off++) { +			for (dst_off = 0; dst_off < MAX_OFFSET; dst_off++) { +				do_one(src, dst, src_off, dst_off, len, +				       redzone, fill); +			} +		} +	} + +	return 0; +} + +int main(void) +{ +	return test_harness(test_copy_loop, str(COPY_LOOP)); +} diff --git a/tools/testing/selftests/powerpc/harness.c b/tools/testing/selftests/powerpc/harness.c index e80c42a584f..8ebc58a0931 100644 --- a/tools/testing/selftests/powerpc/harness.c +++ b/tools/testing/selftests/powerpc/harness.c @@ -30,12 +30,15 @@ int run_test(int (test_function)(void), char *name)  	pid = fork();  	if (pid == 0) { +		setpgid(0, 0);  		exit(test_function());  	} else if (pid == -1) {  		perror("fork");  		return 1;  	} +	setpgid(pid, pid); +  	/* Wake us up in timeout seconds */  	alarm(TIMEOUT);  	terminated = false; @@ -50,17 +53,20 @@ wait:  		if (terminated) {  			printf("!! force killing %s\n", name); -			kill(pid, SIGKILL); +			kill(-pid, SIGKILL);  			return 1;  		} else {  			printf("!! killing %s\n", name); -			kill(pid, SIGTERM); +			kill(-pid, SIGTERM);  			terminated = true;  			alarm(KILL_TIMEOUT);  			goto wait;  		}  	} +	/* Kill anything else in the process group that is still running */ +	kill(-pid, SIGTERM); +  	if (WIFEXITED(status))  		status = WEXITSTATUS(status);  	else { @@ -99,7 +105,10 @@ int test_harness(int (test_function)(void), char *name)  	rc = run_test(test_function, name); -	test_finish(name, rc); +	if (rc == MAGIC_SKIP_RETURN_VALUE) +		test_skip(name); +	else +		test_finish(name, rc);  	return rc;  } diff --git a/tools/testing/selftests/powerpc/mm/Makefile b/tools/testing/selftests/powerpc/mm/Makefile new file mode 100644 index 00000000000..357ccbd6bad --- /dev/null +++ b/tools/testing/selftests/powerpc/mm/Makefile @@ -0,0 +1,18 @@ +noarg: +	$(MAKE) -C ../ + +PROGS := hugetlb_vs_thp_test + +all: $(PROGS) + +$(PROGS): ../harness.c + +run_tests: all +	@-for PROG in $(PROGS); do \ +		./$$PROG; \ +	done; + +clean: +	rm -f $(PROGS) + +.PHONY: all run_tests clean diff --git a/tools/testing/selftests/powerpc/mm/hugetlb_vs_thp_test.c b/tools/testing/selftests/powerpc/mm/hugetlb_vs_thp_test.c new file mode 100644 index 00000000000..3d8e5b033e1 --- /dev/null +++ b/tools/testing/selftests/powerpc/mm/hugetlb_vs_thp_test.c @@ -0,0 +1,72 @@ +#include <stdio.h> +#include <sys/mman.h> +#include <unistd.h> + +#include "utils.h" + +/* This must match the huge page & THP size */ +#define SIZE	(16 * 1024 * 1024) + +static int test_body(void) +{ +	void *addr; +	char *p; + +	addr = (void *)0xa0000000; + +	p = mmap(addr, SIZE, PROT_READ | PROT_WRITE, +		 MAP_HUGETLB | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); +	if (p != MAP_FAILED) { +		/* +		 * Typically the mmap will fail because no huge pages are +		 * allocated on the system. But if there are huge pages +		 * allocated the mmap will succeed. That's fine too, we just +		 * munmap here before continuing. +		 */ +		munmap(addr, SIZE); +	} + +	p = mmap(addr, SIZE, PROT_READ | PROT_WRITE, +		 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); +	if (p == MAP_FAILED) { +		printf("Mapping failed @ %p\n", addr); +		perror("mmap"); +		return 1; +	} + +	/* +	 * Either a user or kernel access is sufficient to trigger the bug. +	 * A kernel access is easier to spot & debug, as it will trigger the +	 * softlockup or RCU stall detectors, and when the system is kicked +	 * into xmon we get a backtrace in the kernel. +	 * +	 * A good option is: +	 *  getcwd(p, SIZE); +	 * +	 * For the purposes of this testcase it's preferable to spin in +	 * userspace, so the harness can kill us if we get stuck. That way we +	 * see a test failure rather than a dead system. +	 */ +	*p = 0xf; + +	munmap(addr, SIZE); + +	return 0; +} + +static int test_main(void) +{ +	int i; + +	/* 10,000 because it's a "bunch", and completes reasonably quickly */ +	for (i = 0; i < 10000; i++) +		if (test_body()) +			return 1; + +	return 0; +} + +int main(void) +{ +	return test_harness(test_main, "hugetlb_vs_thp"); +} diff --git a/tools/testing/selftests/powerpc/pmu/Makefile b/tools/testing/selftests/powerpc/pmu/Makefile index 7216f009165..b9ff0db42c7 100644 --- a/tools/testing/selftests/powerpc/pmu/Makefile +++ b/tools/testing/selftests/powerpc/pmu/Makefile @@ -4,7 +4,7 @@ noarg:  PROGS := count_instructions  EXTRA_SOURCES := ../harness.c event.c -all: $(PROGS) +all: $(PROGS) sub_all  $(PROGS): $(EXTRA_SOURCES) @@ -12,12 +12,30 @@ $(PROGS): $(EXTRA_SOURCES)  count_instructions: loop.S count_instructions.c $(EXTRA_SOURCES)  	$(CC) $(CFLAGS) -m64 -o $@ $^ -run_tests: all +run_tests: all sub_run_tests  	@-for PROG in $(PROGS); do \  		./$$PROG; \  	done; -clean: +clean: sub_clean  	rm -f $(PROGS) loop.o -.PHONY: all run_tests clean + +SUB_TARGETS = ebb + +sub_all: +	@for TARGET in $(SUB_TARGETS); do \ +		$(MAKE) -C $$TARGET all; \ +	done; + +sub_run_tests: all +	@for TARGET in $(SUB_TARGETS); do \ +		$(MAKE) -C $$TARGET run_tests; \ +	done; + +sub_clean: +	@for TARGET in $(SUB_TARGETS); do \ +		$(MAKE) -C $$TARGET clean; \ +	done; + +.PHONY: all run_tests clean sub_all sub_run_tests sub_clean diff --git a/tools/testing/selftests/powerpc/pmu/ebb/Makefile b/tools/testing/selftests/powerpc/pmu/ebb/Makefile new file mode 100644 index 00000000000..edbba2affc2 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/Makefile @@ -0,0 +1,32 @@ +noarg: +	$(MAKE) -C ../../ + +# The EBB handler is 64-bit code and everything links against it +CFLAGS += -m64 + +PROGS := reg_access_test event_attributes_test cycles_test	\ +	 cycles_with_freeze_test pmc56_overflow_test		\ +	 ebb_vs_cpu_event_test cpu_event_vs_ebb_test		\ +	 cpu_event_pinned_vs_ebb_test task_event_vs_ebb_test	\ +	 task_event_pinned_vs_ebb_test multi_ebb_procs_test	\ +	 multi_counter_test pmae_handling_test			\ +	 close_clears_pmcc_test instruction_count_test		\ +	 fork_cleanup_test ebb_on_child_test			\ +	 ebb_on_willing_child_test back_to_back_ebbs_test	\ +	 lost_exception_test no_handler_test + +all: $(PROGS) + +$(PROGS): ../../harness.c ../event.c ../lib.c ebb.c ebb_handler.S trace.c + +instruction_count_test: ../loop.S + +lost_exception_test: ../lib.c + +run_tests: all +	@-for PROG in $(PROGS); do \ +		./$$PROG; \ +	done; + +clean: +	rm -f $(PROGS) diff --git a/tools/testing/selftests/powerpc/pmu/ebb/back_to_back_ebbs_test.c b/tools/testing/selftests/powerpc/pmu/ebb/back_to_back_ebbs_test.c new file mode 100644 index 00000000000..66ea765c0e7 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/back_to_back_ebbs_test.c @@ -0,0 +1,106 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +#include "ebb.h" + + +#define NUMBER_OF_EBBS	50 + +/* + * Test that if we overflow the counter while in the EBB handler, we take + * another EBB on exiting from the handler. + * + * We do this by counting with a stupidly low sample period, causing us to + * overflow the PMU while we're still in the EBB handler, leading to another + * EBB. + * + * We get out of what would otherwise be an infinite loop by leaving the + * counter frozen once we've taken enough EBBs. + */ + +static void ebb_callee(void) +{ +	uint64_t siar, val; + +	val = mfspr(SPRN_BESCR); +	if (!(val & BESCR_PMEO)) { +		ebb_state.stats.spurious++; +		goto out; +	} + +	ebb_state.stats.ebb_count++; +	trace_log_counter(ebb_state.trace, ebb_state.stats.ebb_count); + +	/* Resets the PMC */ +	count_pmc(1, sample_period); + +out: +	if (ebb_state.stats.ebb_count == NUMBER_OF_EBBS) +		/* Reset but leave counters frozen */ +		reset_ebb_with_clear_mask(MMCR0_PMAO); +	else +		/* Unfreezes */ +		reset_ebb(); + +	/* Do some stuff to chew some cycles and pop the counter */ +	siar = mfspr(SPRN_SIAR); +	trace_log_reg(ebb_state.trace, SPRN_SIAR, siar); + +	val = mfspr(SPRN_PMC1); +	trace_log_reg(ebb_state.trace, SPRN_PMC1, val); + +	val = mfspr(SPRN_MMCR0); +	trace_log_reg(ebb_state.trace, SPRN_MMCR0, val); +} + +int back_to_back_ebbs(void) +{ +	struct event event; + +	event_init_named(&event, 0x1001e, "cycles"); +	event_leader_ebb_init(&event); + +	event.attr.exclude_kernel = 1; +	event.attr.exclude_hv = 1; +	event.attr.exclude_idle = 1; + +	FAIL_IF(event_open(&event)); + +	setup_ebb_handler(ebb_callee); + +	FAIL_IF(ebb_event_enable(&event)); + +	sample_period = 5; + +	ebb_freeze_pmcs(); +	mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); +	ebb_global_enable(); +	ebb_unfreeze_pmcs(); + +	while (ebb_state.stats.ebb_count < NUMBER_OF_EBBS) +		FAIL_IF(core_busy_loop()); + +	ebb_global_disable(); +	ebb_freeze_pmcs(); + +	count_pmc(1, sample_period); + +	dump_ebb_state(); + +	event_close(&event); + +	FAIL_IF(ebb_state.stats.ebb_count != NUMBER_OF_EBBS); + +	return 0; +} + +int main(void) +{ +	return test_harness(back_to_back_ebbs, "back_to_back_ebbs"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/close_clears_pmcc_test.c b/tools/testing/selftests/powerpc/pmu/ebb/close_clears_pmcc_test.c new file mode 100644 index 00000000000..0f0423dba18 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/close_clears_pmcc_test.c @@ -0,0 +1,59 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <setjmp.h> +#include <signal.h> + +#include "ebb.h" + + +/* + * Test that closing the EBB event clears MMCR0_PMCC, preventing further access + * by userspace to the PMU hardware. + */ + +int close_clears_pmcc(void) +{ +	struct event event; + +	event_init_named(&event, 0x1001e, "cycles"); +	event_leader_ebb_init(&event); + +	FAIL_IF(event_open(&event)); + +	ebb_enable_pmc_counting(1); +	setup_ebb_handler(standard_ebb_callee); +	ebb_global_enable(); +	FAIL_IF(ebb_event_enable(&event)); + +	mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); + +	while (ebb_state.stats.ebb_count < 1) +		FAIL_IF(core_busy_loop()); + +	ebb_global_disable(); +	event_close(&event); + +	FAIL_IF(ebb_state.stats.ebb_count == 0); + +	/* The real test is here, do we take a SIGILL when writing PMU regs now +	 * that we have closed the event. We expect that we will. */ + +	FAIL_IF(catch_sigill(write_pmc1)); + +	/* We should still be able to read EBB regs though */ +	mfspr(SPRN_EBBHR); +	mfspr(SPRN_EBBRR); +	mfspr(SPRN_BESCR); + +	return 0; +} + +int main(void) +{ +	return test_harness(close_clears_pmcc, "close_clears_pmcc"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/cpu_event_pinned_vs_ebb_test.c b/tools/testing/selftests/powerpc/pmu/ebb/cpu_event_pinned_vs_ebb_test.c new file mode 100644 index 00000000000..d3ed64d5d6c --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/cpu_event_pinned_vs_ebb_test.c @@ -0,0 +1,93 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#include "ebb.h" + + +/* + * Tests a pinned cpu event vs an EBB - in that order. The pinned cpu event + * should remain and the EBB event should fail to enable. + */ + +static int setup_cpu_event(struct event *event, int cpu) +{ +	event_init_named(event, 0x400FA, "PM_RUN_INST_CMPL"); + +	event->attr.pinned = 1; + +	event->attr.exclude_kernel = 1; +	event->attr.exclude_hv = 1; +	event->attr.exclude_idle = 1; + +	SKIP_IF(require_paranoia_below(1)); +	FAIL_IF(event_open_with_cpu(event, cpu)); +	FAIL_IF(event_enable(event)); + +	return 0; +} + +int cpu_event_pinned_vs_ebb(void) +{ +	union pipe read_pipe, write_pipe; +	struct event event; +	int cpu, rc; +	pid_t pid; + +	cpu = pick_online_cpu(); +	FAIL_IF(cpu < 0); +	FAIL_IF(bind_to_cpu(cpu)); + +	FAIL_IF(pipe(read_pipe.fds) == -1); +	FAIL_IF(pipe(write_pipe.fds) == -1); + +	pid = fork(); +	if (pid == 0) { +		/* NB order of pipes looks reversed */ +		exit(ebb_child(write_pipe, read_pipe)); +	} + +	/* We setup the cpu event first */ +	rc = setup_cpu_event(&event, cpu); +	if (rc) { +		kill_child_and_wait(pid); +		return rc; +	} + +	/* Signal the child to install its EBB event and wait */ +	if (sync_with_child(read_pipe, write_pipe)) +		/* If it fails, wait for it to exit */ +		goto wait; + +	/* Signal the child to run */ +	FAIL_IF(sync_with_child(read_pipe, write_pipe)); + +wait: +	/* We expect it to fail to read the event */ +	FAIL_IF(wait_for_child(pid) != 2); + +	FAIL_IF(event_disable(&event)); +	FAIL_IF(event_read(&event)); + +	event_report(&event); + +	/* The cpu event should have run */ +	FAIL_IF(event.result.value == 0); +	FAIL_IF(event.result.enabled != event.result.running); + +	return 0; +} + +int main(void) +{ +	return test_harness(cpu_event_pinned_vs_ebb, "cpu_event_pinned_vs_ebb"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/cpu_event_vs_ebb_test.c b/tools/testing/selftests/powerpc/pmu/ebb/cpu_event_vs_ebb_test.c new file mode 100644 index 00000000000..8b972c2aa39 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/cpu_event_vs_ebb_test.c @@ -0,0 +1,89 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#include "ebb.h" + + +/* + * Tests a cpu event vs an EBB - in that order. The EBB should force the cpu + * event off the PMU. + */ + +static int setup_cpu_event(struct event *event, int cpu) +{ +	event_init_named(event, 0x400FA, "PM_RUN_INST_CMPL"); + +	event->attr.exclude_kernel = 1; +	event->attr.exclude_hv = 1; +	event->attr.exclude_idle = 1; + +	SKIP_IF(require_paranoia_below(1)); +	FAIL_IF(event_open_with_cpu(event, cpu)); +	FAIL_IF(event_enable(event)); + +	return 0; +} + +int cpu_event_vs_ebb(void) +{ +	union pipe read_pipe, write_pipe; +	struct event event; +	int cpu, rc; +	pid_t pid; + +	cpu = pick_online_cpu(); +	FAIL_IF(cpu < 0); +	FAIL_IF(bind_to_cpu(cpu)); + +	FAIL_IF(pipe(read_pipe.fds) == -1); +	FAIL_IF(pipe(write_pipe.fds) == -1); + +	pid = fork(); +	if (pid == 0) { +		/* NB order of pipes looks reversed */ +		exit(ebb_child(write_pipe, read_pipe)); +	} + +	/* We setup the cpu event first */ +	rc = setup_cpu_event(&event, cpu); +	if (rc) { +		kill_child_and_wait(pid); +		return rc; +	} + +	/* Signal the child to install its EBB event and wait */ +	if (sync_with_child(read_pipe, write_pipe)) +		/* If it fails, wait for it to exit */ +		goto wait; + +	/* Signal the child to run */ +	FAIL_IF(sync_with_child(read_pipe, write_pipe)); + +wait: +	/* We expect the child to succeed */ +	FAIL_IF(wait_for_child(pid)); + +	FAIL_IF(event_disable(&event)); +	FAIL_IF(event_read(&event)); + +	event_report(&event); + +	/* The cpu event may have run */ + +	return 0; +} + +int main(void) +{ +	return test_harness(cpu_event_vs_ebb, "cpu_event_vs_ebb"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/cycles_test.c b/tools/testing/selftests/powerpc/pmu/ebb/cycles_test.c new file mode 100644 index 00000000000..8590fc1bfc0 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/cycles_test.c @@ -0,0 +1,58 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "ebb.h" + + +/* + * Basic test that counts user cycles and takes EBBs. + */ +int cycles(void) +{ +	struct event event; + +	event_init_named(&event, 0x1001e, "cycles"); +	event_leader_ebb_init(&event); + +	event.attr.exclude_kernel = 1; +	event.attr.exclude_hv = 1; +	event.attr.exclude_idle = 1; + +	FAIL_IF(event_open(&event)); + +	ebb_enable_pmc_counting(1); +	setup_ebb_handler(standard_ebb_callee); +	ebb_global_enable(); +	FAIL_IF(ebb_event_enable(&event)); + +	mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); + +	while (ebb_state.stats.ebb_count < 10) { +		FAIL_IF(core_busy_loop()); +		FAIL_IF(ebb_check_mmcr0()); +	} + +	ebb_global_disable(); +	ebb_freeze_pmcs(); + +	count_pmc(1, sample_period); + +	dump_ebb_state(); + +	event_close(&event); + +	FAIL_IF(ebb_state.stats.ebb_count == 0); +	FAIL_IF(!ebb_check_count(1, sample_period, 100)); + +	return 0; +} + +int main(void) +{ +	return test_harness(cycles, "cycles"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_freeze_test.c b/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_freeze_test.c new file mode 100644 index 00000000000..754b3f2008d --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_freeze_test.c @@ -0,0 +1,117 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> + +#include "ebb.h" + + +/* + * Test of counting cycles while using MMCR0_FC (freeze counters) to only count + * parts of the code. This is complicated by the fact that FC is set by the + * hardware when the event overflows. We may take the EBB after we have set FC, + * so we have to be careful about whether we clear FC at the end of the EBB + * handler or not. + */ + +static bool counters_frozen = false; +static int ebbs_while_frozen = 0; + +static void ebb_callee(void) +{ +	uint64_t mask, val; + +	mask = MMCR0_PMAO | MMCR0_FC; + +	val = mfspr(SPRN_BESCR); +	if (!(val & BESCR_PMEO)) { +		ebb_state.stats.spurious++; +		goto out; +	} + +	ebb_state.stats.ebb_count++; +	trace_log_counter(ebb_state.trace, ebb_state.stats.ebb_count); + +	val = mfspr(SPRN_MMCR0); +	trace_log_reg(ebb_state.trace, SPRN_MMCR0, val); + +	if (counters_frozen) { +		trace_log_string(ebb_state.trace, "frozen"); +		ebbs_while_frozen++; +		mask &= ~MMCR0_FC; +	} + +	count_pmc(1, sample_period); +out: +	reset_ebb_with_clear_mask(mask); +} + +int cycles_with_freeze(void) +{ +	struct event event; +	uint64_t val; +	bool fc_cleared; + +	event_init_named(&event, 0x1001e, "cycles"); +	event_leader_ebb_init(&event); + +	event.attr.exclude_kernel = 1; +	event.attr.exclude_hv = 1; +	event.attr.exclude_idle = 1; + +	FAIL_IF(event_open(&event)); + +	setup_ebb_handler(ebb_callee); +	ebb_global_enable(); +	FAIL_IF(ebb_event_enable(&event)); + +	mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); + +	fc_cleared = false; + +	/* Make sure we loop until we take at least one EBB */ +	while ((ebb_state.stats.ebb_count < 20 && !fc_cleared) || +		ebb_state.stats.ebb_count < 1) +	{ +		counters_frozen = false; +		mb(); +		mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) & ~MMCR0_FC); + +		FAIL_IF(core_busy_loop()); + +		counters_frozen = true; +		mb(); +		mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) |  MMCR0_FC); + +		val = mfspr(SPRN_MMCR0); +		if (! (val & MMCR0_FC)) { +			printf("Outside of loop, FC NOT set MMCR0 0x%lx\n", val); +			fc_cleared = true; +		} +	} + +	ebb_global_disable(); +	ebb_freeze_pmcs(); + +	count_pmc(1, sample_period); + +	dump_ebb_state(); + +	printf("EBBs while frozen %d\n", ebbs_while_frozen); + +	event_close(&event); + +	FAIL_IF(ebb_state.stats.ebb_count == 0); +	FAIL_IF(fc_cleared); + +	return 0; +} + +int main(void) +{ +	return test_harness(cycles_with_freeze, "cycles_with_freeze"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb.c new file mode 100644 index 00000000000..1b46be94b64 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb.c @@ -0,0 +1,727 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#define _GNU_SOURCE	/* For CPU_ZERO etc. */ + +#include <sched.h> +#include <sys/wait.h> +#include <setjmp.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> + +#include "trace.h" +#include "reg.h" +#include "ebb.h" + + +void (*ebb_user_func)(void); + +void ebb_hook(void) +{ +	if (ebb_user_func) +		ebb_user_func(); +} + +struct ebb_state ebb_state; + +u64 sample_period = 0x40000000ull; + +void reset_ebb_with_clear_mask(unsigned long mmcr0_clear_mask) +{ +	u64 val; + +	/* 2) clear MMCR0[PMAO] - docs say BESCR[PMEO] should do this */ +	/* 3) set MMCR0[PMAE]	- docs say BESCR[PME] should do this */ +	val = mfspr(SPRN_MMCR0); +	mtspr(SPRN_MMCR0, (val & ~mmcr0_clear_mask) | MMCR0_PMAE); + +	/* 4) clear BESCR[PMEO] */ +	mtspr(SPRN_BESCRR, BESCR_PMEO); + +	/* 5) set BESCR[PME] */ +	mtspr(SPRN_BESCRS, BESCR_PME); + +	/* 6) rfebb 1 - done in our caller */ +} + +void reset_ebb(void) +{ +	reset_ebb_with_clear_mask(MMCR0_PMAO | MMCR0_FC); +} + +/* Called outside of the EBB handler to check MMCR0 is sane */ +int ebb_check_mmcr0(void) +{ +	u64 val; + +	val = mfspr(SPRN_MMCR0); +	if ((val & (MMCR0_FC | MMCR0_PMAO)) == MMCR0_FC) { +		/* It's OK if we see FC & PMAO, but not FC by itself */ +		printf("Outside of loop, only FC set 0x%llx\n", val); +		return 1; +	} + +	return 0; +} + +bool ebb_check_count(int pmc, u64 sample_period, int fudge) +{ +	u64 count, upper, lower; + +	count = ebb_state.stats.pmc_count[PMC_INDEX(pmc)]; + +	lower = ebb_state.stats.ebb_count * (sample_period - fudge); + +	if (count < lower) { +		printf("PMC%d count (0x%llx) below lower limit 0x%llx (-0x%llx)\n", +			pmc, count, lower, lower - count); +		return false; +	} + +	upper = ebb_state.stats.ebb_count * (sample_period + fudge); + +	if (count > upper) { +		printf("PMC%d count (0x%llx) above upper limit 0x%llx (+0x%llx)\n", +			pmc, count, upper, count - upper); +		return false; +	} + +	printf("PMC%d count (0x%llx) is between 0x%llx and 0x%llx delta +0x%llx/-0x%llx\n", +		pmc, count, lower, upper, count - lower, upper - count); + +	return true; +} + +void standard_ebb_callee(void) +{ +	int found, i; +	u64 val; + +	val = mfspr(SPRN_BESCR); +	if (!(val & BESCR_PMEO)) { +		ebb_state.stats.spurious++; +		goto out; +	} + +	ebb_state.stats.ebb_count++; +	trace_log_counter(ebb_state.trace, ebb_state.stats.ebb_count); + +	val = mfspr(SPRN_MMCR0); +	trace_log_reg(ebb_state.trace, SPRN_MMCR0, val); + +	found = 0; +	for (i = 1; i <= 6; i++) { +		if (ebb_state.pmc_enable[PMC_INDEX(i)]) +			found += count_pmc(i, sample_period); +	} + +	if (!found) +		ebb_state.stats.no_overflow++; + +out: +	reset_ebb(); +} + +extern void ebb_handler(void); + +void setup_ebb_handler(void (*callee)(void)) +{ +	u64 entry; + +#if defined(_CALL_ELF) && _CALL_ELF == 2 +	entry = (u64)ebb_handler; +#else +	struct opd +	{ +	    u64 entry; +	    u64 toc; +	} *opd; + +	opd = (struct opd *)ebb_handler; +	entry = opd->entry; +#endif +	printf("EBB Handler is at %#llx\n", entry); + +	ebb_user_func = callee; + +	/* Ensure ebb_user_func is set before we set the handler */ +	mb(); +	mtspr(SPRN_EBBHR, entry); + +	/* Make sure the handler is set before we return */ +	mb(); +} + +void clear_ebb_stats(void) +{ +	memset(&ebb_state.stats, 0, sizeof(ebb_state.stats)); +} + +void dump_summary_ebb_state(void) +{ +	printf("ebb_state:\n"			\ +	       "  ebb_count    = %d\n"		\ +	       "  spurious     = %d\n"		\ +	       "  negative     = %d\n"		\ +	       "  no_overflow  = %d\n"		\ +	       "  pmc[1] count = 0x%llx\n"	\ +	       "  pmc[2] count = 0x%llx\n"	\ +	       "  pmc[3] count = 0x%llx\n"	\ +	       "  pmc[4] count = 0x%llx\n"	\ +	       "  pmc[5] count = 0x%llx\n"	\ +	       "  pmc[6] count = 0x%llx\n", +		ebb_state.stats.ebb_count, ebb_state.stats.spurious, +		ebb_state.stats.negative, ebb_state.stats.no_overflow, +		ebb_state.stats.pmc_count[0], ebb_state.stats.pmc_count[1], +		ebb_state.stats.pmc_count[2], ebb_state.stats.pmc_count[3], +		ebb_state.stats.pmc_count[4], ebb_state.stats.pmc_count[5]); +} + +static char *decode_mmcr0(u32 value) +{ +	static char buf[16]; + +	buf[0] = '\0'; + +	if (value & (1 << 31)) +		strcat(buf, "FC "); +	if (value & (1 << 26)) +		strcat(buf, "PMAE "); +	if (value & (1 << 7)) +		strcat(buf, "PMAO "); + +	return buf; +} + +static char *decode_bescr(u64 value) +{ +	static char buf[16]; + +	buf[0] = '\0'; + +	if (value & (1ull << 63)) +		strcat(buf, "GE "); +	if (value & (1ull << 32)) +		strcat(buf, "PMAE "); +	if (value & 1) +		strcat(buf, "PMAO "); + +	return buf; +} + +void dump_ebb_hw_state(void) +{ +	u64 bescr; +	u32 mmcr0; + +	mmcr0 = mfspr(SPRN_MMCR0); +	bescr = mfspr(SPRN_BESCR); + +	printf("HW state:\n"		\ +	       "MMCR0 0x%016x %s\n"	\ +	       "EBBHR 0x%016lx\n"	\ +	       "BESCR 0x%016llx %s\n"	\ +	       "PMC1  0x%016lx\n"	\ +	       "PMC2  0x%016lx\n"	\ +	       "PMC3  0x%016lx\n"	\ +	       "PMC4  0x%016lx\n"	\ +	       "PMC5  0x%016lx\n"	\ +	       "PMC6  0x%016lx\n"	\ +	       "SIAR  0x%016lx\n", +	       mmcr0, decode_mmcr0(mmcr0), mfspr(SPRN_EBBHR), bescr, +	       decode_bescr(bescr), mfspr(SPRN_PMC1), mfspr(SPRN_PMC2), +	       mfspr(SPRN_PMC3), mfspr(SPRN_PMC4), mfspr(SPRN_PMC5), +	       mfspr(SPRN_PMC6), mfspr(SPRN_SIAR)); +} + +void dump_ebb_state(void) +{ +	dump_summary_ebb_state(); + +	dump_ebb_hw_state(); + +	trace_buffer_print(ebb_state.trace); +} + +int count_pmc(int pmc, uint32_t sample_period) +{ +	uint32_t start_value; +	u64 val; + +	/* 0) Read PMC */ +	start_value = pmc_sample_period(sample_period); + +	val = read_pmc(pmc); +	if (val < start_value) +		ebb_state.stats.negative++; +	else +		ebb_state.stats.pmc_count[PMC_INDEX(pmc)] += val - start_value; + +	trace_log_reg(ebb_state.trace, SPRN_PMC1 + pmc - 1, val); + +	/* 1) Reset PMC */ +	write_pmc(pmc, start_value); + +	/* Report if we overflowed */ +	return val >= COUNTER_OVERFLOW; +} + +int ebb_event_enable(struct event *e) +{ +	int rc; + +	/* Ensure any SPR writes are ordered vs us */ +	mb(); + +	rc = ioctl(e->fd, PERF_EVENT_IOC_ENABLE); +	if (rc) +		return rc; + +	rc = event_read(e); + +	/* Ditto */ +	mb(); + +	return rc; +} + +void ebb_freeze_pmcs(void) +{ +	mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) | MMCR0_FC); +	mb(); +} + +void ebb_unfreeze_pmcs(void) +{ +	/* Unfreeze counters */ +	mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) & ~MMCR0_FC); +	mb(); +} + +void ebb_global_enable(void) +{ +	/* Enable EBBs globally and PMU EBBs */ +	mtspr(SPRN_BESCR, 0x8000000100000000ull); +	mb(); +} + +void ebb_global_disable(void) +{ +	/* Disable EBBs & freeze counters, events are still scheduled */ +	mtspr(SPRN_BESCRR, BESCR_PME); +	mb(); +} + +void event_ebb_init(struct event *e) +{ +	e->attr.config |= (1ull << 63); +} + +void event_bhrb_init(struct event *e, unsigned ifm) +{ +	e->attr.config |= (1ull << 62) | ((u64)ifm << 60); +} + +void event_leader_ebb_init(struct event *e) +{ +	event_ebb_init(e); + +	e->attr.exclusive = 1; +	e->attr.pinned = 1; +} + +int core_busy_loop(void) +{ +	int rc; + +	asm volatile ( +		"li  3,  0x3030\n" +		"std 3,  -96(1)\n" +		"li  4,  0x4040\n" +		"std 4,  -104(1)\n" +		"li  5,  0x5050\n" +		"std 5,  -112(1)\n" +		"li  6,  0x6060\n" +		"std 6,  -120(1)\n" +		"li  7,  0x7070\n" +		"std 7,  -128(1)\n" +		"li  8,  0x0808\n" +		"std 8,  -136(1)\n" +		"li  9,  0x0909\n" +		"std 9,  -144(1)\n" +		"li  10, 0x1010\n" +		"std 10, -152(1)\n" +		"li  11, 0x1111\n" +		"std 11, -160(1)\n" +		"li  14, 0x1414\n" +		"std 14, -168(1)\n" +		"li  15, 0x1515\n" +		"std 15, -176(1)\n" +		"li  16, 0x1616\n" +		"std 16, -184(1)\n" +		"li  17, 0x1717\n" +		"std 17, -192(1)\n" +		"li  18, 0x1818\n" +		"std 18, -200(1)\n" +		"li  19, 0x1919\n" +		"std 19, -208(1)\n" +		"li  20, 0x2020\n" +		"std 20, -216(1)\n" +		"li  21, 0x2121\n" +		"std 21, -224(1)\n" +		"li  22, 0x2222\n" +		"std 22, -232(1)\n" +		"li  23, 0x2323\n" +		"std 23, -240(1)\n" +		"li  24, 0x2424\n" +		"std 24, -248(1)\n" +		"li  25, 0x2525\n" +		"std 25, -256(1)\n" +		"li  26, 0x2626\n" +		"std 26, -264(1)\n" +		"li  27, 0x2727\n" +		"std 27, -272(1)\n" +		"li  28, 0x2828\n" +		"std 28, -280(1)\n" +		"li  29, 0x2929\n" +		"std 29, -288(1)\n" +		"li  30, 0x3030\n" +		"li  31, 0x3131\n" + +		"li    3,  0\n" +		"0: " +		"addi  3, 3, 1\n" +		"cmpwi 3, 100\n" +		"blt   0b\n" + +		/* Return 1 (fail) unless we get through all the checks */ +		"li	0, 1\n" + +		/* Check none of our registers have been corrupted */ +		"cmpwi  4,  0x4040\n" +		"bne	1f\n" +		"cmpwi  5,  0x5050\n" +		"bne	1f\n" +		"cmpwi  6,  0x6060\n" +		"bne	1f\n" +		"cmpwi  7,  0x7070\n" +		"bne	1f\n" +		"cmpwi  8,  0x0808\n" +		"bne	1f\n" +		"cmpwi  9,  0x0909\n" +		"bne	1f\n" +		"cmpwi  10, 0x1010\n" +		"bne	1f\n" +		"cmpwi  11, 0x1111\n" +		"bne	1f\n" +		"cmpwi  14, 0x1414\n" +		"bne	1f\n" +		"cmpwi  15, 0x1515\n" +		"bne	1f\n" +		"cmpwi  16, 0x1616\n" +		"bne	1f\n" +		"cmpwi  17, 0x1717\n" +		"bne	1f\n" +		"cmpwi  18, 0x1818\n" +		"bne	1f\n" +		"cmpwi  19, 0x1919\n" +		"bne	1f\n" +		"cmpwi  20, 0x2020\n" +		"bne	1f\n" +		"cmpwi  21, 0x2121\n" +		"bne	1f\n" +		"cmpwi  22, 0x2222\n" +		"bne	1f\n" +		"cmpwi  23, 0x2323\n" +		"bne	1f\n" +		"cmpwi  24, 0x2424\n" +		"bne	1f\n" +		"cmpwi  25, 0x2525\n" +		"bne	1f\n" +		"cmpwi  26, 0x2626\n" +		"bne	1f\n" +		"cmpwi  27, 0x2727\n" +		"bne	1f\n" +		"cmpwi  28, 0x2828\n" +		"bne	1f\n" +		"cmpwi  29, 0x2929\n" +		"bne	1f\n" +		"cmpwi  30, 0x3030\n" +		"bne	1f\n" +		"cmpwi  31, 0x3131\n" +		"bne	1f\n" + +		/* Load junk into all our registers before we reload them from the stack. */ +		"li  3,  0xde\n" +		"li  4,  0xad\n" +		"li  5,  0xbe\n" +		"li  6,  0xef\n" +		"li  7,  0xde\n" +		"li  8,  0xad\n" +		"li  9,  0xbe\n" +		"li  10, 0xef\n" +		"li  11, 0xde\n" +		"li  14, 0xad\n" +		"li  15, 0xbe\n" +		"li  16, 0xef\n" +		"li  17, 0xde\n" +		"li  18, 0xad\n" +		"li  19, 0xbe\n" +		"li  20, 0xef\n" +		"li  21, 0xde\n" +		"li  22, 0xad\n" +		"li  23, 0xbe\n" +		"li  24, 0xef\n" +		"li  25, 0xde\n" +		"li  26, 0xad\n" +		"li  27, 0xbe\n" +		"li  28, 0xef\n" +		"li  29, 0xdd\n" + +		"ld     3,  -96(1)\n" +		"cmpwi  3,  0x3030\n" +		"bne	1f\n" +		"ld     4,  -104(1)\n" +		"cmpwi  4,  0x4040\n" +		"bne	1f\n" +		"ld     5,  -112(1)\n" +		"cmpwi  5,  0x5050\n" +		"bne	1f\n" +		"ld     6,  -120(1)\n" +		"cmpwi  6,  0x6060\n" +		"bne	1f\n" +		"ld     7,  -128(1)\n" +		"cmpwi  7,  0x7070\n" +		"bne	1f\n" +		"ld     8,  -136(1)\n" +		"cmpwi  8,  0x0808\n" +		"bne	1f\n" +		"ld     9,  -144(1)\n" +		"cmpwi  9,  0x0909\n" +		"bne	1f\n" +		"ld     10, -152(1)\n" +		"cmpwi  10, 0x1010\n" +		"bne	1f\n" +		"ld     11, -160(1)\n" +		"cmpwi  11, 0x1111\n" +		"bne	1f\n" +		"ld     14, -168(1)\n" +		"cmpwi  14, 0x1414\n" +		"bne	1f\n" +		"ld     15, -176(1)\n" +		"cmpwi  15, 0x1515\n" +		"bne	1f\n" +		"ld     16, -184(1)\n" +		"cmpwi  16, 0x1616\n" +		"bne	1f\n" +		"ld     17, -192(1)\n" +		"cmpwi  17, 0x1717\n" +		"bne	1f\n" +		"ld     18, -200(1)\n" +		"cmpwi  18, 0x1818\n" +		"bne	1f\n" +		"ld     19, -208(1)\n" +		"cmpwi  19, 0x1919\n" +		"bne	1f\n" +		"ld     20, -216(1)\n" +		"cmpwi  20, 0x2020\n" +		"bne	1f\n" +		"ld     21, -224(1)\n" +		"cmpwi  21, 0x2121\n" +		"bne	1f\n" +		"ld     22, -232(1)\n" +		"cmpwi  22, 0x2222\n" +		"bne	1f\n" +		"ld     23, -240(1)\n" +		"cmpwi  23, 0x2323\n" +		"bne	1f\n" +		"ld     24, -248(1)\n" +		"cmpwi  24, 0x2424\n" +		"bne	1f\n" +		"ld     25, -256(1)\n" +		"cmpwi  25, 0x2525\n" +		"bne	1f\n" +		"ld     26, -264(1)\n" +		"cmpwi  26, 0x2626\n" +		"bne	1f\n" +		"ld     27, -272(1)\n" +		"cmpwi  27, 0x2727\n" +		"bne	1f\n" +		"ld     28, -280(1)\n" +		"cmpwi  28, 0x2828\n" +		"bne	1f\n" +		"ld     29, -288(1)\n" +		"cmpwi  29, 0x2929\n" +		"bne	1f\n" + +		/* Load 0 (success) to return */ +		"li	0, 0\n" + +		"1: 	mr %0, 0\n" + +		: "=r" (rc) +		: /* no inputs */ +		: "3", "4", "5", "6", "7", "8", "9", "10", "11", "14", +		  "15", "16", "17", "18", "19", "20", "21", "22", "23", +		   "24", "25", "26", "27", "28", "29", "30", "31", +		   "memory" +	); + +	return rc; +} + +int core_busy_loop_with_freeze(void) +{ +	int rc; + +	mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) & ~MMCR0_FC); +	rc = core_busy_loop(); +	mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) |  MMCR0_FC); + +	return rc; +} + +int ebb_child(union pipe read_pipe, union pipe write_pipe) +{ +	struct event event; +	uint64_t val; + +	FAIL_IF(wait_for_parent(read_pipe)); + +	event_init_named(&event, 0x1001e, "cycles"); +	event_leader_ebb_init(&event); + +	event.attr.exclude_kernel = 1; +	event.attr.exclude_hv = 1; +	event.attr.exclude_idle = 1; + +	FAIL_IF(event_open(&event)); + +	ebb_enable_pmc_counting(1); +	setup_ebb_handler(standard_ebb_callee); +	ebb_global_enable(); + +	FAIL_IF(event_enable(&event)); + +	if (event_read(&event)) { +		/* +		 * Some tests expect to fail here, so don't report an error on +		 * this line, and return a distinguisable error code. Tell the +		 * parent an error happened. +		 */ +		notify_parent_of_error(write_pipe); +		return 2; +	} + +	mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); + +	FAIL_IF(notify_parent(write_pipe)); +	FAIL_IF(wait_for_parent(read_pipe)); +	FAIL_IF(notify_parent(write_pipe)); + +	while (ebb_state.stats.ebb_count < 20) { +		FAIL_IF(core_busy_loop()); + +		/* To try and hit SIGILL case */ +		val  = mfspr(SPRN_MMCRA); +		val |= mfspr(SPRN_MMCR2); +		val |= mfspr(SPRN_MMCR0); +	} + +	ebb_global_disable(); +	ebb_freeze_pmcs(); + +	count_pmc(1, sample_period); + +	dump_ebb_state(); + +	event_close(&event); + +	FAIL_IF(ebb_state.stats.ebb_count == 0); + +	return 0; +} + +static jmp_buf setjmp_env; + +static void sigill_handler(int signal) +{ +	printf("Took sigill\n"); +	longjmp(setjmp_env, 1); +} + +static struct sigaction sigill_action = { +	.sa_handler = sigill_handler, +}; + +int catch_sigill(void (*func)(void)) +{ +	if (sigaction(SIGILL, &sigill_action, NULL)) { +		perror("sigaction"); +		return 1; +	} + +	if (setjmp(setjmp_env) == 0) { +		func(); +		return 1; +	} + +	return 0; +} + +void write_pmc1(void) +{ +	mtspr(SPRN_PMC1, 0); +} + +void write_pmc(int pmc, u64 value) +{ +	switch (pmc) { +		case 1: mtspr(SPRN_PMC1, value); break; +		case 2: mtspr(SPRN_PMC2, value); break; +		case 3: mtspr(SPRN_PMC3, value); break; +		case 4: mtspr(SPRN_PMC4, value); break; +		case 5: mtspr(SPRN_PMC5, value); break; +		case 6: mtspr(SPRN_PMC6, value); break; +	} +} + +u64 read_pmc(int pmc) +{ +	switch (pmc) { +		case 1: return mfspr(SPRN_PMC1); +		case 2: return mfspr(SPRN_PMC2); +		case 3: return mfspr(SPRN_PMC3); +		case 4: return mfspr(SPRN_PMC4); +		case 5: return mfspr(SPRN_PMC5); +		case 6: return mfspr(SPRN_PMC6); +	} + +	return 0; +} + +static void term_handler(int signal) +{ +	dump_summary_ebb_state(); +	dump_ebb_hw_state(); +	abort(); +} + +struct sigaction term_action = { +	.sa_handler = term_handler, +}; + +static void __attribute__((constructor)) ebb_init(void) +{ +	clear_ebb_stats(); + +	if (sigaction(SIGTERM, &term_action, NULL)) +		perror("sigaction"); + +	ebb_state.trace = trace_buffer_allocate(1 * 1024 * 1024); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb.h b/tools/testing/selftests/powerpc/pmu/ebb/ebb.h new file mode 100644 index 00000000000..e62bde05bf7 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb.h @@ -0,0 +1,78 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#ifndef _SELFTESTS_POWERPC_PMU_EBB_EBB_H +#define _SELFTESTS_POWERPC_PMU_EBB_EBB_H + +#include "../event.h" +#include "../lib.h" +#include "trace.h" +#include "reg.h" + +#define PMC_INDEX(pmc)	((pmc)-1) + +#define NUM_PMC_VALUES	128 + +struct ebb_state +{ +	struct { +		u64 pmc_count[6]; +		volatile int ebb_count; +		int spurious; +		int negative; +		int no_overflow; +	} stats; + +	bool pmc_enable[6]; +	struct trace_buffer *trace; +}; + +extern struct ebb_state ebb_state; + +#define COUNTER_OVERFLOW 0x80000000ull + +static inline uint32_t pmc_sample_period(uint32_t value) +{ +	return COUNTER_OVERFLOW - value; +} + +static inline void ebb_enable_pmc_counting(int pmc) +{ +	ebb_state.pmc_enable[PMC_INDEX(pmc)] = true; +} + +bool ebb_check_count(int pmc, u64 sample_period, int fudge); +void event_leader_ebb_init(struct event *e); +void event_ebb_init(struct event *e); +void event_bhrb_init(struct event *e, unsigned ifm); +void setup_ebb_handler(void (*callee)(void)); +void standard_ebb_callee(void); +int ebb_event_enable(struct event *e); +void ebb_global_enable(void); +void ebb_global_disable(void); +void ebb_freeze_pmcs(void); +void ebb_unfreeze_pmcs(void); +void event_ebb_init(struct event *e); +void event_leader_ebb_init(struct event *e); +int count_pmc(int pmc, uint32_t sample_period); +void dump_ebb_state(void); +void dump_summary_ebb_state(void); +void dump_ebb_hw_state(void); +void clear_ebb_stats(void); +void write_pmc(int pmc, u64 value); +u64 read_pmc(int pmc); +void reset_ebb_with_clear_mask(unsigned long mmcr0_clear_mask); +void reset_ebb(void); +int ebb_check_mmcr0(void); + +extern u64 sample_period; + +int core_busy_loop(void); +int core_busy_loop_with_freeze(void); +int ebb_child(union pipe read_pipe, union pipe write_pipe); +int catch_sigill(void (*func)(void)); +void write_pmc1(void); + +#endif /* _SELFTESTS_POWERPC_PMU_EBB_EBB_H */ diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb_handler.S b/tools/testing/selftests/powerpc/pmu/ebb/ebb_handler.S new file mode 100644 index 00000000000..14274ea206e --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb_handler.S @@ -0,0 +1,365 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <ppc-asm.h> +#include "reg.h" + + +/* ppc-asm.h defines most of the reg aliases, but not r1/r2. */ +#define r1 1 +#define r2 2 + +#define RFEBB   .long 0x4c000924 + +/* Stack layout: + * + *                   ^ + *  User stack       | + *  Back chain ------+	<- r1		<-------+ + *  ...						| + *  Red zone / ABI Gap				| + *  ...						| + *  vr63	<+				| + *  vr0		 |				| + *  VSCR	 |				| + *  FSCR	 |				| + *  r31		 | Save area			| + *  r0		 |				| + *  XER		 |				| + *  CTR		 |				| + *  LR		 |				| + *  CCR		<+				| + *  ...		<+				| + *  LR		 | Caller frame			| + *  CCR		 |				| + *  Back chain	<+	<- updated r1	--------+ + * + */ + +#if defined(_CALL_ELF) && _CALL_ELF == 2 +#define ABIGAP		512 +#else +#define ABIGAP		288 +#endif + +#define NR_GPR		32 +#define NR_SPR		6 +#define NR_VSR		64 + +#define SAVE_AREA	((NR_GPR + NR_SPR) * 8 + (NR_VSR * 16)) +#define CALLER_FRAME	112 + +#define STACK_FRAME	(ABIGAP + SAVE_AREA + CALLER_FRAME) + +#define CCR_SAVE	(CALLER_FRAME) +#define LR_SAVE		(CCR_SAVE + 8) +#define CTR_SAVE	(LR_SAVE  + 8) +#define XER_SAVE	(CTR_SAVE + 8) +#define GPR_SAVE(n)	(XER_SAVE + 8 + (8 * n)) +#define FSCR_SAVE	(GPR_SAVE(31) + 8) +#define VSCR_SAVE	(FSCR_SAVE + 8) +#define VSR_SAVE(n)	(VSCR_SAVE + 8 + (16 * n)) + +#define SAVE_GPR(n)	std n,GPR_SAVE(n)(r1) +#define REST_GPR(n)	ld  n,GPR_SAVE(n)(r1) +#define TRASH_GPR(n)	lis n,0xaaaa + +#define SAVE_VSR(n, b)	li b, VSR_SAVE(n); stxvd2x n,b,r1 +#define LOAD_VSR(n, b)	li b, VSR_SAVE(n); lxvd2x  n,b,r1 + +#define LOAD_REG_IMMEDIATE(reg,expr)	\ +	lis     reg,(expr)@highest;	\ +	ori     reg,reg,(expr)@higher;	\ +	rldicr  reg,reg,32,31;		\ +	oris    reg,reg,(expr)@h;	\ +	ori     reg,reg,(expr)@l; + + +#if defined(_CALL_ELF) && _CALL_ELF == 2 +#define ENTRY_POINT(name) \ +	.type FUNC_NAME(name),@function; \ +	.globl FUNC_NAME(name); \ +	FUNC_NAME(name): + +#define RESTORE_TOC(name)	\ +	/* Restore our TOC pointer using our entry point */	\ +	LOAD_REG_IMMEDIATE(r12, name)				\ +0:	addis	r2,r12,(.TOC.-0b)@ha;				\ +	addi	r2,r2,(.TOC.-0b)@l; + +#else +#define ENTRY_POINT(name) FUNC_START(name) +#define RESTORE_TOC(name)	\ +	/* Restore our TOC pointer via our opd entry */	\ +	LOAD_REG_IMMEDIATE(r2, name)			\ +	ld      r2,8(r2); +#endif + +    .text + +ENTRY_POINT(ebb_handler) +    stdu    r1,-STACK_FRAME(r1) +    SAVE_GPR(0) +    mflr    r0 +    std     r0,LR_SAVE(r1) +    mfcr    r0 +    std     r0,CCR_SAVE(r1) +    mfctr   r0 +    std     r0,CTR_SAVE(r1) +    mfxer   r0 +    std     r0,XER_SAVE(r1) +    SAVE_GPR(2) +    SAVE_GPR(3) +    SAVE_GPR(4) +    SAVE_GPR(5) +    SAVE_GPR(6) +    SAVE_GPR(7) +    SAVE_GPR(8) +    SAVE_GPR(9) +    SAVE_GPR(10) +    SAVE_GPR(11) +    SAVE_GPR(12) +    SAVE_GPR(13) +    SAVE_GPR(14) +    SAVE_GPR(15) +    SAVE_GPR(16) +    SAVE_GPR(17) +    SAVE_GPR(18) +    SAVE_GPR(19) +    SAVE_GPR(20) +    SAVE_GPR(21) +    SAVE_GPR(22) +    SAVE_GPR(23) +    SAVE_GPR(24) +    SAVE_GPR(25) +    SAVE_GPR(26) +    SAVE_GPR(27) +    SAVE_GPR(28) +    SAVE_GPR(29) +    SAVE_GPR(30) +    SAVE_GPR(31) +    SAVE_VSR(0, r3) +    mffs     f0 +    stfd     f0, FSCR_SAVE(r1) +    mfvscr   f0 +    stfd     f0, VSCR_SAVE(r1) +    SAVE_VSR(1,  r3) +    SAVE_VSR(2,  r3) +    SAVE_VSR(3,  r3) +    SAVE_VSR(4,  r3) +    SAVE_VSR(5,  r3) +    SAVE_VSR(6,  r3) +    SAVE_VSR(7,  r3) +    SAVE_VSR(8,  r3) +    SAVE_VSR(9,  r3) +    SAVE_VSR(10, r3) +    SAVE_VSR(11, r3) +    SAVE_VSR(12, r3) +    SAVE_VSR(13, r3) +    SAVE_VSR(14, r3) +    SAVE_VSR(15, r3) +    SAVE_VSR(16, r3) +    SAVE_VSR(17, r3) +    SAVE_VSR(18, r3) +    SAVE_VSR(19, r3) +    SAVE_VSR(20, r3) +    SAVE_VSR(21, r3) +    SAVE_VSR(22, r3) +    SAVE_VSR(23, r3) +    SAVE_VSR(24, r3) +    SAVE_VSR(25, r3) +    SAVE_VSR(26, r3) +    SAVE_VSR(27, r3) +    SAVE_VSR(28, r3) +    SAVE_VSR(29, r3) +    SAVE_VSR(30, r3) +    SAVE_VSR(31, r3) +    SAVE_VSR(32, r3) +    SAVE_VSR(33, r3) +    SAVE_VSR(34, r3) +    SAVE_VSR(35, r3) +    SAVE_VSR(36, r3) +    SAVE_VSR(37, r3) +    SAVE_VSR(38, r3) +    SAVE_VSR(39, r3) +    SAVE_VSR(40, r3) +    SAVE_VSR(41, r3) +    SAVE_VSR(42, r3) +    SAVE_VSR(43, r3) +    SAVE_VSR(44, r3) +    SAVE_VSR(45, r3) +    SAVE_VSR(46, r3) +    SAVE_VSR(47, r3) +    SAVE_VSR(48, r3) +    SAVE_VSR(49, r3) +    SAVE_VSR(50, r3) +    SAVE_VSR(51, r3) +    SAVE_VSR(52, r3) +    SAVE_VSR(53, r3) +    SAVE_VSR(54, r3) +    SAVE_VSR(55, r3) +    SAVE_VSR(56, r3) +    SAVE_VSR(57, r3) +    SAVE_VSR(58, r3) +    SAVE_VSR(59, r3) +    SAVE_VSR(60, r3) +    SAVE_VSR(61, r3) +    SAVE_VSR(62, r3) +    SAVE_VSR(63, r3) + +    TRASH_GPR(2) +    TRASH_GPR(3) +    TRASH_GPR(4) +    TRASH_GPR(5) +    TRASH_GPR(6) +    TRASH_GPR(7) +    TRASH_GPR(8) +    TRASH_GPR(9) +    TRASH_GPR(10) +    TRASH_GPR(11) +    TRASH_GPR(12) +    TRASH_GPR(14) +    TRASH_GPR(15) +    TRASH_GPR(16) +    TRASH_GPR(17) +    TRASH_GPR(18) +    TRASH_GPR(19) +    TRASH_GPR(20) +    TRASH_GPR(21) +    TRASH_GPR(22) +    TRASH_GPR(23) +    TRASH_GPR(24) +    TRASH_GPR(25) +    TRASH_GPR(26) +    TRASH_GPR(27) +    TRASH_GPR(28) +    TRASH_GPR(29) +    TRASH_GPR(30) +    TRASH_GPR(31) + +    RESTORE_TOC(ebb_handler) + +    /* +     * r13 is our TLS pointer. We leave whatever value was in there when the +     * EBB fired. That seems to be OK because once set the TLS pointer is not +     * changed - but presumably that could change in future. +     */ + +    bl      ebb_hook +    nop + +    /* r2 may be changed here but we don't care */ + +    lfd      f0, FSCR_SAVE(r1) +    mtfsf    0xff,f0 +    lfd      f0, VSCR_SAVE(r1) +    mtvscr   f0 +    LOAD_VSR(0, r3) +    LOAD_VSR(1,  r3) +    LOAD_VSR(2,  r3) +    LOAD_VSR(3,  r3) +    LOAD_VSR(4,  r3) +    LOAD_VSR(5,  r3) +    LOAD_VSR(6,  r3) +    LOAD_VSR(7,  r3) +    LOAD_VSR(8,  r3) +    LOAD_VSR(9,  r3) +    LOAD_VSR(10, r3) +    LOAD_VSR(11, r3) +    LOAD_VSR(12, r3) +    LOAD_VSR(13, r3) +    LOAD_VSR(14, r3) +    LOAD_VSR(15, r3) +    LOAD_VSR(16, r3) +    LOAD_VSR(17, r3) +    LOAD_VSR(18, r3) +    LOAD_VSR(19, r3) +    LOAD_VSR(20, r3) +    LOAD_VSR(21, r3) +    LOAD_VSR(22, r3) +    LOAD_VSR(23, r3) +    LOAD_VSR(24, r3) +    LOAD_VSR(25, r3) +    LOAD_VSR(26, r3) +    LOAD_VSR(27, r3) +    LOAD_VSR(28, r3) +    LOAD_VSR(29, r3) +    LOAD_VSR(30, r3) +    LOAD_VSR(31, r3) +    LOAD_VSR(32, r3) +    LOAD_VSR(33, r3) +    LOAD_VSR(34, r3) +    LOAD_VSR(35, r3) +    LOAD_VSR(36, r3) +    LOAD_VSR(37, r3) +    LOAD_VSR(38, r3) +    LOAD_VSR(39, r3) +    LOAD_VSR(40, r3) +    LOAD_VSR(41, r3) +    LOAD_VSR(42, r3) +    LOAD_VSR(43, r3) +    LOAD_VSR(44, r3) +    LOAD_VSR(45, r3) +    LOAD_VSR(46, r3) +    LOAD_VSR(47, r3) +    LOAD_VSR(48, r3) +    LOAD_VSR(49, r3) +    LOAD_VSR(50, r3) +    LOAD_VSR(51, r3) +    LOAD_VSR(52, r3) +    LOAD_VSR(53, r3) +    LOAD_VSR(54, r3) +    LOAD_VSR(55, r3) +    LOAD_VSR(56, r3) +    LOAD_VSR(57, r3) +    LOAD_VSR(58, r3) +    LOAD_VSR(59, r3) +    LOAD_VSR(60, r3) +    LOAD_VSR(61, r3) +    LOAD_VSR(62, r3) +    LOAD_VSR(63, r3) + +    ld      r0,XER_SAVE(r1) +    mtxer   r0 +    ld      r0,CTR_SAVE(r1) +    mtctr   r0 +    ld      r0,LR_SAVE(r1) +    mtlr    r0 +    ld      r0,CCR_SAVE(r1) +    mtcr    r0 +    REST_GPR(0) +    REST_GPR(2) +    REST_GPR(3) +    REST_GPR(4) +    REST_GPR(5) +    REST_GPR(6) +    REST_GPR(7) +    REST_GPR(8) +    REST_GPR(9) +    REST_GPR(10) +    REST_GPR(11) +    REST_GPR(12) +    REST_GPR(13) +    REST_GPR(14) +    REST_GPR(15) +    REST_GPR(16) +    REST_GPR(17) +    REST_GPR(18) +    REST_GPR(19) +    REST_GPR(20) +    REST_GPR(21) +    REST_GPR(22) +    REST_GPR(23) +    REST_GPR(24) +    REST_GPR(25) +    REST_GPR(26) +    REST_GPR(27) +    REST_GPR(28) +    REST_GPR(29) +    REST_GPR(30) +    REST_GPR(31) +    addi    r1,r1,STACK_FRAME +    RFEBB +FUNC_END(ebb_handler) diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb_on_child_test.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb_on_child_test.c new file mode 100644 index 00000000000..c45f948148e --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb_on_child_test.c @@ -0,0 +1,86 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#include "ebb.h" + + +/* + * Tests we can setup an EBB on our child. Nothing interesting happens, because + * even though the event is enabled and running the child hasn't enabled the + * actual delivery of the EBBs. + */ + +static int victim_child(union pipe read_pipe, union pipe write_pipe) +{ +	int i; + +	FAIL_IF(wait_for_parent(read_pipe)); +	FAIL_IF(notify_parent(write_pipe)); + +	/* Parent creates EBB event */ + +	FAIL_IF(wait_for_parent(read_pipe)); +	FAIL_IF(notify_parent(write_pipe)); + +	/* Check the EBB is enabled by writing PMC1 */ +	write_pmc1(); + +	/* EBB event is enabled here */ +	for (i = 0; i < 1000000; i++) ; + +	return 0; +} + +int ebb_on_child(void) +{ +	union pipe read_pipe, write_pipe; +	struct event event; +	pid_t pid; + +	FAIL_IF(pipe(read_pipe.fds) == -1); +	FAIL_IF(pipe(write_pipe.fds) == -1); + +	pid = fork(); +	if (pid == 0) { +		/* NB order of pipes looks reversed */ +		exit(victim_child(write_pipe, read_pipe)); +	} + +	FAIL_IF(sync_with_child(read_pipe, write_pipe)); + +	/* Child is running now */ + +	event_init_named(&event, 0x1001e, "cycles"); +	event_leader_ebb_init(&event); + +	event.attr.exclude_kernel = 1; +	event.attr.exclude_hv = 1; +	event.attr.exclude_idle = 1; + +	FAIL_IF(event_open_with_pid(&event, pid)); +	FAIL_IF(ebb_event_enable(&event)); + +	FAIL_IF(sync_with_child(read_pipe, write_pipe)); + +	/* Child should just exit happily */ +	FAIL_IF(wait_for_child(pid)); + +	event_close(&event); + +	return 0; +} + +int main(void) +{ +	return test_harness(ebb_on_child, "ebb_on_child"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb_on_willing_child_test.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb_on_willing_child_test.c new file mode 100644 index 00000000000..11acf1d55f8 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb_on_willing_child_test.c @@ -0,0 +1,92 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#include "ebb.h" + + +/* + * Tests we can setup an EBB on our child. The child expects this and enables + * EBBs, which are then delivered to the child, even though the event is + * created by the parent. + */ + +static int victim_child(union pipe read_pipe, union pipe write_pipe) +{ +	FAIL_IF(wait_for_parent(read_pipe)); + +	/* Setup our EBB handler, before the EBB event is created */ +	ebb_enable_pmc_counting(1); +	setup_ebb_handler(standard_ebb_callee); +	ebb_global_enable(); + +	FAIL_IF(notify_parent(write_pipe)); + +	while (ebb_state.stats.ebb_count < 20) { +		FAIL_IF(core_busy_loop()); +	} + +	ebb_global_disable(); +	ebb_freeze_pmcs(); + +	count_pmc(1, sample_period); + +	dump_ebb_state(); + +	FAIL_IF(ebb_state.stats.ebb_count == 0); + +	return 0; +} + +/* Tests we can setup an EBB on our child - if it's expecting it */ +int ebb_on_willing_child(void) +{ +	union pipe read_pipe, write_pipe; +	struct event event; +	pid_t pid; + +	FAIL_IF(pipe(read_pipe.fds) == -1); +	FAIL_IF(pipe(write_pipe.fds) == -1); + +	pid = fork(); +	if (pid == 0) { +		/* NB order of pipes looks reversed */ +		exit(victim_child(write_pipe, read_pipe)); +	} + +	/* Signal the child to setup its EBB handler */ +	FAIL_IF(sync_with_child(read_pipe, write_pipe)); + +	/* Child is running now */ + +	event_init_named(&event, 0x1001e, "cycles"); +	event_leader_ebb_init(&event); + +	event.attr.exclude_kernel = 1; +	event.attr.exclude_hv = 1; +	event.attr.exclude_idle = 1; + +	FAIL_IF(event_open_with_pid(&event, pid)); +	FAIL_IF(ebb_event_enable(&event)); + +	/* Child show now take EBBs and then exit */ +	FAIL_IF(wait_for_child(pid)); + +	event_close(&event); + +	return 0; +} + +int main(void) +{ +	return test_harness(ebb_on_willing_child, "ebb_on_willing_child"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb_vs_cpu_event_test.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb_vs_cpu_event_test.c new file mode 100644 index 00000000000..be4dd5a4e98 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb_vs_cpu_event_test.c @@ -0,0 +1,86 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#include "ebb.h" + + +/* + * Tests an EBB vs a cpu event - in that order. The EBB should force the cpu + * event off the PMU. + */ + +static int setup_cpu_event(struct event *event, int cpu) +{ +	event_init_named(event, 0x400FA, "PM_RUN_INST_CMPL"); + +	event->attr.exclude_kernel = 1; +	event->attr.exclude_hv = 1; +	event->attr.exclude_idle = 1; + +	SKIP_IF(require_paranoia_below(1)); +	FAIL_IF(event_open_with_cpu(event, cpu)); +	FAIL_IF(event_enable(event)); + +	return 0; +} + +int ebb_vs_cpu_event(void) +{ +	union pipe read_pipe, write_pipe; +	struct event event; +	int cpu, rc; +	pid_t pid; + +	cpu = pick_online_cpu(); +	FAIL_IF(cpu < 0); +	FAIL_IF(bind_to_cpu(cpu)); + +	FAIL_IF(pipe(read_pipe.fds) == -1); +	FAIL_IF(pipe(write_pipe.fds) == -1); + +	pid = fork(); +	if (pid == 0) { +		/* NB order of pipes looks reversed */ +		exit(ebb_child(write_pipe, read_pipe)); +	} + +	/* Signal the child to install its EBB event and wait */ +	FAIL_IF(sync_with_child(read_pipe, write_pipe)); + +	/* Now try to install our CPU event */ +	rc = setup_cpu_event(&event, cpu); +	if (rc) { +		kill_child_and_wait(pid); +		return rc; +	} + +	/* Signal the child to run */ +	FAIL_IF(sync_with_child(read_pipe, write_pipe)); + +	/* .. and wait for it to complete */ +	FAIL_IF(wait_for_child(pid)); +	FAIL_IF(event_disable(&event)); +	FAIL_IF(event_read(&event)); + +	event_report(&event); + +	/* The cpu event may have run, but we don't expect 100% */ +	FAIL_IF(event.result.enabled >= event.result.running); + +	return 0; +} + +int main(void) +{ +	return test_harness(ebb_vs_cpu_event, "ebb_vs_cpu_event"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/event_attributes_test.c b/tools/testing/selftests/powerpc/pmu/ebb/event_attributes_test.c new file mode 100644 index 00000000000..7e78153f08e --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/event_attributes_test.c @@ -0,0 +1,131 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "ebb.h" + + +/* + * Test various attributes of the EBB event are enforced. + */ +int event_attributes(void) +{ +	struct event event, leader; + +	event_init(&event, 0x1001e); +	event_leader_ebb_init(&event); +	/* Expected to succeed */ +	FAIL_IF(event_open(&event)); +	event_close(&event); + + +	event_init(&event, 0x001e); /* CYCLES - no PMC specified */ +	event_leader_ebb_init(&event); +	/* Expected to fail, no PMC specified */ +	FAIL_IF(event_open(&event) == 0); + + +	event_init(&event, 0x2001e); +	event_leader_ebb_init(&event); +	event.attr.exclusive = 0; +	/* Expected to fail, not exclusive */ +	FAIL_IF(event_open(&event) == 0); + + +	event_init(&event, 0x3001e); +	event_leader_ebb_init(&event); +	event.attr.freq = 1; +	/* Expected to fail, sets freq */ +	FAIL_IF(event_open(&event) == 0); + + +	event_init(&event, 0x4001e); +	event_leader_ebb_init(&event); +	event.attr.sample_period = 1; +	/* Expected to fail, sets sample_period */ +	FAIL_IF(event_open(&event) == 0); + + +	event_init(&event, 0x1001e); +	event_leader_ebb_init(&event); +	event.attr.enable_on_exec = 1; +	/* Expected to fail, sets enable_on_exec */ +	FAIL_IF(event_open(&event) == 0); + + +	event_init(&event, 0x1001e); +	event_leader_ebb_init(&event); +	event.attr.inherit = 1; +	/* Expected to fail, sets inherit */ +	FAIL_IF(event_open(&event) == 0); + + +	event_init(&leader, 0x1001e); +	event_leader_ebb_init(&leader); +	FAIL_IF(event_open(&leader)); + +	event_init(&event, 0x20002); +	event_ebb_init(&event); + +	/* Expected to succeed */ +	FAIL_IF(event_open_with_group(&event, leader.fd)); +	event_close(&leader); +	event_close(&event); + + +	event_init(&leader, 0x1001e); +	event_leader_ebb_init(&leader); +	FAIL_IF(event_open(&leader)); + +	event_init(&event, 0x20002); + +	/* Expected to fail, event doesn't request EBB, leader does */ +	FAIL_IF(event_open_with_group(&event, leader.fd) == 0); +	event_close(&leader); + + +	event_init(&leader, 0x1001e); +	event_leader_ebb_init(&leader); +	/* Clear the EBB flag */ +	leader.attr.config &= ~(1ull << 63); + +	FAIL_IF(event_open(&leader)); + +	event_init(&event, 0x20002); +	event_ebb_init(&event); + +	/* Expected to fail, leader doesn't request EBB */ +	FAIL_IF(event_open_with_group(&event, leader.fd) == 0); +	event_close(&leader); + + +	event_init(&leader, 0x1001e); +	event_leader_ebb_init(&leader); +	leader.attr.exclusive = 0; +	/* Expected to fail, leader isn't exclusive */ +	FAIL_IF(event_open(&leader) == 0); + + +	event_init(&leader, 0x1001e); +	event_leader_ebb_init(&leader); +	leader.attr.pinned = 0; +	/* Expected to fail, leader isn't pinned */ +	FAIL_IF(event_open(&leader) == 0); + +	event_init(&event, 0x1001e); +	event_leader_ebb_init(&event); +	/* Expected to fail, not a task event */ +	SKIP_IF(require_paranoia_below(1)); +	FAIL_IF(event_open_with_cpu(&event, 0) == 0); + +	return 0; +} + +int main(void) +{ +	return test_harness(event_attributes, "event_attributes"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/fixed_instruction_loop.S b/tools/testing/selftests/powerpc/pmu/ebb/fixed_instruction_loop.S new file mode 100644 index 00000000000..b866a0581d3 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/fixed_instruction_loop.S @@ -0,0 +1,43 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <ppc-asm.h> + +	.text + +FUNC_START(thirty_two_instruction_loop) +	cmpwi	r3,0 +	beqlr +	addi	r4,r3,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1	# 28 addi's +	subi	r3,r3,1 +	b	FUNC_NAME(thirty_two_instruction_loop) +FUNC_END(thirty_two_instruction_loop) diff --git a/tools/testing/selftests/powerpc/pmu/ebb/fork_cleanup_test.c b/tools/testing/selftests/powerpc/pmu/ebb/fork_cleanup_test.c new file mode 100644 index 00000000000..9e7af6e7662 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/fork_cleanup_test.c @@ -0,0 +1,79 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <setjmp.h> +#include <signal.h> + +#include "ebb.h" + + +/* + * Test that a fork clears the PMU state of the child. eg. BESCR/EBBHR/EBBRR + * are cleared, and MMCR0_PMCC is reset, preventing the child from accessing + * the PMU. + */ + +static struct event event; + +static int child(void) +{ +	/* Even though we have EBE=0 we can still see the EBB regs */ +	FAIL_IF(mfspr(SPRN_BESCR) != 0); +	FAIL_IF(mfspr(SPRN_EBBHR) != 0); +	FAIL_IF(mfspr(SPRN_EBBRR) != 0); + +	FAIL_IF(catch_sigill(write_pmc1)); + +	/* We can still read from the event, though it is on our parent */ +	FAIL_IF(event_read(&event)); + +	return 0; +} + +/* Tests that fork clears EBB state */ +int fork_cleanup(void) +{ +	pid_t pid; + +	event_init_named(&event, 0x1001e, "cycles"); +	event_leader_ebb_init(&event); + +	FAIL_IF(event_open(&event)); + +	ebb_enable_pmc_counting(1); +	setup_ebb_handler(standard_ebb_callee); +	ebb_global_enable(); + +	FAIL_IF(ebb_event_enable(&event)); + +	mtspr(SPRN_MMCR0, MMCR0_FC); +	mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); + +	/* Don't need to actually take any EBBs */ + +	pid = fork(); +	if (pid == 0) +		exit(child()); + +	/* Child does the actual testing */ +	FAIL_IF(wait_for_child(pid)); + +	/* After fork */ +	event_close(&event); + +	return 0; +} + +int main(void) +{ +	return test_harness(fork_cleanup, "fork_cleanup"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c b/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c new file mode 100644 index 00000000000..f8190fa2959 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c @@ -0,0 +1,164 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdbool.h> +#include <string.h> +#include <sys/prctl.h> + +#include "ebb.h" + + +/* + * Run a calibrated instruction loop and count instructions executed using + * EBBs. Make sure the counts look right. + */ + +extern void thirty_two_instruction_loop(uint64_t loops); + +static bool counters_frozen = true; + +static int do_count_loop(struct event *event, uint64_t instructions, +			 uint64_t overhead, bool report) +{ +	int64_t difference, expected; +	double percentage; + +	clear_ebb_stats(); + +	counters_frozen = false; +	mb(); +	mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) & ~MMCR0_FC); + +	thirty_two_instruction_loop(instructions >> 5); + +	counters_frozen = true; +	mb(); +	mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) | MMCR0_FC); + +	count_pmc(4, sample_period); + +	event->result.value = ebb_state.stats.pmc_count[4-1]; +	expected = instructions + overhead; +	difference = event->result.value - expected; +	percentage = (double)difference / event->result.value * 100; + +	if (report) { +		printf("Looped for %lu instructions, overhead %lu\n", instructions, overhead); +		printf("Expected %lu\n", expected); +		printf("Actual   %llu\n", event->result.value); +		printf("Error    %ld, %f%%\n", difference, percentage); +		printf("Took %d EBBs\n", ebb_state.stats.ebb_count); +	} + +	if (difference < 0) +		difference = -difference; + +	/* Tolerate a difference of up to 0.0001 % */ +	difference *= 10000 * 100; +	if (difference / event->result.value) +		return -1; + +	return 0; +} + +/* Count how many instructions it takes to do a null loop */ +static uint64_t determine_overhead(struct event *event) +{ +	uint64_t current, overhead; +	int i; + +	do_count_loop(event, 0, 0, false); +	overhead = event->result.value; + +	for (i = 0; i < 100; i++) { +		do_count_loop(event, 0, 0, false); +		current = event->result.value; +		if (current < overhead) { +			printf("Replacing overhead %lu with %lu\n", overhead, current); +			overhead = current; +		} +	} + +	return overhead; +} + +static void pmc4_ebb_callee(void) +{ +	uint64_t val; + +	val = mfspr(SPRN_BESCR); +	if (!(val & BESCR_PMEO)) { +		ebb_state.stats.spurious++; +		goto out; +	} + +	ebb_state.stats.ebb_count++; +	count_pmc(4, sample_period); +out: +	if (counters_frozen) +		reset_ebb_with_clear_mask(MMCR0_PMAO); +	else +		reset_ebb(); +} + +int instruction_count(void) +{ +	struct event event; +	uint64_t overhead; + +	event_init_named(&event, 0x400FA, "PM_RUN_INST_CMPL"); +	event_leader_ebb_init(&event); +	event.attr.exclude_kernel = 1; +	event.attr.exclude_hv = 1; +	event.attr.exclude_idle = 1; + +	FAIL_IF(event_open(&event)); +	FAIL_IF(ebb_event_enable(&event)); + +	sample_period = COUNTER_OVERFLOW; + +	setup_ebb_handler(pmc4_ebb_callee); +	mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) & ~MMCR0_FC); +	ebb_global_enable(); + +	overhead = determine_overhead(&event); +	printf("Overhead of null loop: %lu instructions\n", overhead); + +	/* Run for 1M instructions */ +	FAIL_IF(do_count_loop(&event, 0x100000, overhead, true)); + +	/* Run for 10M instructions */ +	FAIL_IF(do_count_loop(&event, 0xa00000, overhead, true)); + +	/* Run for 100M instructions */ +	FAIL_IF(do_count_loop(&event, 0x6400000, overhead, true)); + +	/* Run for 1G instructions */ +	FAIL_IF(do_count_loop(&event, 0x40000000, overhead, true)); + +	/* Run for 16G instructions */ +	FAIL_IF(do_count_loop(&event, 0x400000000, overhead, true)); + +	/* Run for 64G instructions */ +	FAIL_IF(do_count_loop(&event, 0x1000000000, overhead, true)); + +	/* Run for 128G instructions */ +	FAIL_IF(do_count_loop(&event, 0x2000000000, overhead, true)); + +	ebb_global_disable(); +	event_close(&event); + +	printf("Finished OK\n"); + +	return 0; +} + +int main(void) +{ +	return test_harness(instruction_count, "instruction_count"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c b/tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c new file mode 100644 index 00000000000..0c9dd9b2e39 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c @@ -0,0 +1,100 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <sched.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/mman.h> + +#include "ebb.h" + + +/* + * Test that tries to trigger CPU_FTR_PMAO_BUG. Which is a hardware defect + * where an exception triggers but we context switch before it is delivered and + * lose the exception. + */ + +static int test_body(void) +{ +	int i, orig_period, max_period; +	struct event event; + +	/* We use PMC4 to make sure the kernel switches all counters correctly */ +	event_init_named(&event, 0x40002, "instructions"); +	event_leader_ebb_init(&event); + +	event.attr.exclude_kernel = 1; +	event.attr.exclude_hv = 1; +	event.attr.exclude_idle = 1; + +	FAIL_IF(event_open(&event)); + +	ebb_enable_pmc_counting(4); +	setup_ebb_handler(standard_ebb_callee); +	ebb_global_enable(); +	FAIL_IF(ebb_event_enable(&event)); + +	/* +	 * We want a low sample period, but we also want to get out of the EBB +	 * handler without tripping up again. +	 * +	 * This value picked after much experimentation. +	 */ +	orig_period = max_period = sample_period = 400; + +	mtspr(SPRN_PMC4, pmc_sample_period(sample_period)); + +	while (ebb_state.stats.ebb_count < 1000000) { +		/* +		 * We are trying to get the EBB exception to race exactly with +		 * us entering the kernel to do the syscall. We then need the +		 * kernel to decide our timeslice is up and context switch to +		 * the other thread. When we come back our EBB will have been +		 * lost and we'll spin in this while loop forever. +		 */ + +		for (i = 0; i < 100000; i++) +			sched_yield(); + +		/* Change the sample period slightly to try and hit the race */ +		if (sample_period >= (orig_period + 200)) +			sample_period = orig_period; +		else +			sample_period++; + +		if (sample_period > max_period) +			max_period = sample_period; +	} + +	ebb_freeze_pmcs(); +	ebb_global_disable(); + +	count_pmc(4, sample_period); +	mtspr(SPRN_PMC4, 0xdead); + +	dump_summary_ebb_state(); +	dump_ebb_hw_state(); + +	event_close(&event); + +	FAIL_IF(ebb_state.stats.ebb_count == 0); + +	/* We vary our sample period so we need extra fudge here */ +	FAIL_IF(!ebb_check_count(4, orig_period, 2 * (max_period - orig_period))); + +	return 0; +} + +static int lost_exception(void) +{ +	return eat_cpu(test_body); +} + +int main(void) +{ +	return test_harness(lost_exception, "lost_exception"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/multi_counter_test.c b/tools/testing/selftests/powerpc/pmu/ebb/multi_counter_test.c new file mode 100644 index 00000000000..67d78af3284 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/multi_counter_test.c @@ -0,0 +1,91 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/ioctl.h> + +#include "ebb.h" + + +/* + * Test counting multiple events using EBBs. + */ +int multi_counter(void) +{ +	struct event events[6]; +	int i, group_fd; + +	event_init_named(&events[0], 0x1001C, "PM_CMPLU_STALL_THRD"); +	event_init_named(&events[1], 0x2D016, "PM_CMPLU_STALL_FXU"); +	event_init_named(&events[2], 0x30006, "PM_CMPLU_STALL_OTHER_CMPL"); +	event_init_named(&events[3], 0x4000A, "PM_CMPLU_STALL"); +	event_init_named(&events[4], 0x600f4, "PM_RUN_CYC"); +	event_init_named(&events[5], 0x500fa, "PM_RUN_INST_CMPL"); + +	event_leader_ebb_init(&events[0]); +	for (i = 1; i < 6; i++) +		event_ebb_init(&events[i]); + +	group_fd = -1; +	for (i = 0; i < 6; i++) { +		events[i].attr.exclude_kernel = 1; +		events[i].attr.exclude_hv = 1; +		events[i].attr.exclude_idle = 1; + +		FAIL_IF(event_open_with_group(&events[i], group_fd)); +		if (group_fd == -1) +			group_fd = events[0].fd; +	} + +	ebb_enable_pmc_counting(1); +	ebb_enable_pmc_counting(2); +	ebb_enable_pmc_counting(3); +	ebb_enable_pmc_counting(4); +	ebb_enable_pmc_counting(5); +	ebb_enable_pmc_counting(6); +	setup_ebb_handler(standard_ebb_callee); + +	FAIL_IF(ioctl(events[0].fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP)); +	FAIL_IF(event_read(&events[0])); + +	ebb_global_enable(); + +	mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); +	mtspr(SPRN_PMC2, pmc_sample_period(sample_period)); +	mtspr(SPRN_PMC3, pmc_sample_period(sample_period)); +	mtspr(SPRN_PMC4, pmc_sample_period(sample_period)); +	mtspr(SPRN_PMC5, pmc_sample_period(sample_period)); +	mtspr(SPRN_PMC6, pmc_sample_period(sample_period)); + +	while (ebb_state.stats.ebb_count < 50) { +		FAIL_IF(core_busy_loop()); +		FAIL_IF(ebb_check_mmcr0()); +	} + +	ebb_global_disable(); +	ebb_freeze_pmcs(); + +	count_pmc(1, sample_period); +	count_pmc(2, sample_period); +	count_pmc(3, sample_period); +	count_pmc(4, sample_period); +	count_pmc(5, sample_period); +	count_pmc(6, sample_period); + +	dump_ebb_state(); + +	for (i = 0; i < 6; i++) +		event_close(&events[i]); + +	FAIL_IF(ebb_state.stats.ebb_count == 0); + +	return 0; +} + +int main(void) +{ +	return test_harness(multi_counter, "multi_counter"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/multi_ebb_procs_test.c b/tools/testing/selftests/powerpc/pmu/ebb/multi_ebb_procs_test.c new file mode 100644 index 00000000000..b8dc371f933 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/multi_ebb_procs_test.c @@ -0,0 +1,109 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> + +#include "ebb.h" + + +/* + * Test running multiple EBB using processes at once on a single CPU. They + * should all run happily without interfering with each other. + */ + +static bool child_should_exit; + +static void sigint_handler(int signal) +{ +	child_should_exit = true; +} + +struct sigaction sigint_action = { +	.sa_handler = sigint_handler, +}; + +static int cycles_child(void) +{ +	struct event event; + +	if (sigaction(SIGINT, &sigint_action, NULL)) { +		perror("sigaction"); +		return 1; +	} + +	event_init_named(&event, 0x1001e, "cycles"); +	event_leader_ebb_init(&event); + +	event.attr.exclude_kernel = 1; +	event.attr.exclude_hv = 1; +	event.attr.exclude_idle = 1; + +	FAIL_IF(event_open(&event)); + +	ebb_enable_pmc_counting(1); +	setup_ebb_handler(standard_ebb_callee); +	ebb_global_enable(); + +	FAIL_IF(ebb_event_enable(&event)); + +	mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); + +	while (!child_should_exit) { +		FAIL_IF(core_busy_loop()); +		FAIL_IF(ebb_check_mmcr0()); +	} + +	ebb_global_disable(); +	ebb_freeze_pmcs(); + +	count_pmc(1, sample_period); + +	dump_summary_ebb_state(); + +	event_close(&event); + +	FAIL_IF(ebb_state.stats.ebb_count == 0); + +	return 0; +} + +#define NR_CHILDREN	4 + +int multi_ebb_procs(void) +{ +	pid_t pids[NR_CHILDREN]; +	int cpu, rc, i; + +	cpu = pick_online_cpu(); +	FAIL_IF(cpu < 0); +	FAIL_IF(bind_to_cpu(cpu)); + +	for (i = 0; i < NR_CHILDREN; i++) { +		pids[i] = fork(); +		if (pids[i] == 0) +			exit(cycles_child()); +	} + +	/* Have them all run for "a while" */ +	sleep(10); + +	rc = 0; +	for (i = 0; i < NR_CHILDREN; i++) { +		/* Tell them to stop */ +		kill(pids[i], SIGINT); +		/* And wait */ +		rc |= wait_for_child(pids[i]); +	} + +	return rc; +} + +int main(void) +{ +	return test_harness(multi_ebb_procs, "multi_ebb_procs"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/no_handler_test.c b/tools/testing/selftests/powerpc/pmu/ebb/no_handler_test.c new file mode 100644 index 00000000000..2f9bf8edfa6 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/no_handler_test.c @@ -0,0 +1,61 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <setjmp.h> +#include <signal.h> + +#include "ebb.h" + + +/* Test that things work sanely if we have no handler */ + +static int no_handler_test(void) +{ +	struct event event; +	u64 val; +	int i; + +	event_init_named(&event, 0x1001e, "cycles"); +	event_leader_ebb_init(&event); + +	event.attr.exclude_kernel = 1; +	event.attr.exclude_hv = 1; +	event.attr.exclude_idle = 1; + +	FAIL_IF(event_open(&event)); +	FAIL_IF(ebb_event_enable(&event)); + +	val = mfspr(SPRN_EBBHR); +	FAIL_IF(val != 0); + +	/* Make sure it overflows quickly */ +	sample_period = 1000; +	mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); + +	/* Spin to make sure the event has time to overflow */ +	for (i = 0; i < 1000; i++) +		mb(); + +	dump_ebb_state(); + +	/* We expect to see the PMU frozen & PMAO set */ +	val = mfspr(SPRN_MMCR0); +	FAIL_IF(val != 0x0000000080000080); + +	event_close(&event); + +	dump_ebb_state(); + +	/* The real test is that we never took an EBB at 0x0 */ + +	return 0; +} + +int main(void) +{ +	return test_harness(no_handler_test,"no_handler_test"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/pmae_handling_test.c b/tools/testing/selftests/powerpc/pmu/ebb/pmae_handling_test.c new file mode 100644 index 00000000000..986500fd213 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/pmae_handling_test.c @@ -0,0 +1,106 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <sched.h> +#include <signal.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +#include "ebb.h" + + +/* + * Test that the kernel properly handles PMAE across context switches. + * + * We test this by calling into the kernel inside our EBB handler, where PMAE + * is clear. A cpu eater companion thread is running on the same CPU as us to + * encourage the scheduler to switch us. + * + * The kernel must make sure that when it context switches us back in, it + * honours the fact that we had PMAE clear. + * + * Observed to hit the failing case on the first EBB with a broken kernel. + */ + +static bool mmcr0_mismatch; +static uint64_t before, after; + +static void syscall_ebb_callee(void) +{ +	uint64_t val; + +	val = mfspr(SPRN_BESCR); +	if (!(val & BESCR_PMEO)) { +		ebb_state.stats.spurious++; +		goto out; +	} + +	ebb_state.stats.ebb_count++; +	count_pmc(1, sample_period); + +	before = mfspr(SPRN_MMCR0); + +	/* Try and get ourselves scheduled, to force a PMU context switch */ +	sched_yield(); + +	after = mfspr(SPRN_MMCR0); +	if (before != after) +		mmcr0_mismatch = true; + +out: +	reset_ebb(); +} + +static int test_body(void) +{ +	struct event event; + +	event_init_named(&event, 0x1001e, "cycles"); +	event_leader_ebb_init(&event); + +	event.attr.exclude_kernel = 1; +	event.attr.exclude_hv = 1; +	event.attr.exclude_idle = 1; + +	FAIL_IF(event_open(&event)); + +	setup_ebb_handler(syscall_ebb_callee); +	ebb_global_enable(); + +	FAIL_IF(ebb_event_enable(&event)); + +	mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); + +	while (ebb_state.stats.ebb_count < 20 && !mmcr0_mismatch) +		FAIL_IF(core_busy_loop()); + +	ebb_global_disable(); +	ebb_freeze_pmcs(); + +	count_pmc(1, sample_period); + +	dump_ebb_state(); + +	if (mmcr0_mismatch) +		printf("Saw MMCR0 before 0x%lx after 0x%lx\n", before, after); + +	event_close(&event); + +	FAIL_IF(ebb_state.stats.ebb_count == 0); +	FAIL_IF(mmcr0_mismatch); + +	return 0; +} + +int pmae_handling(void) +{ +	return eat_cpu(test_body); +} + +int main(void) +{ +	return test_harness(pmae_handling, "pmae_handling"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c b/tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c new file mode 100644 index 00000000000..a503fa70c95 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c @@ -0,0 +1,93 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "ebb.h" + + +/* + * Test that PMC5 & 6 are frozen (ie. don't overflow) when they are not being + * used. Tests the MMCR0_FC56 logic in the kernel. + */ + +static int pmc56_overflowed; + +static void ebb_callee(void) +{ +	uint64_t val; + +	val = mfspr(SPRN_BESCR); +	if (!(val & BESCR_PMEO)) { +		ebb_state.stats.spurious++; +		goto out; +	} + +	ebb_state.stats.ebb_count++; +	count_pmc(2, sample_period); + +	val = mfspr(SPRN_PMC5); +	if (val >= COUNTER_OVERFLOW) +		pmc56_overflowed++; + +	count_pmc(5, COUNTER_OVERFLOW); + +	val = mfspr(SPRN_PMC6); +	if (val >= COUNTER_OVERFLOW) +		pmc56_overflowed++; + +	count_pmc(6, COUNTER_OVERFLOW); + +out: +	reset_ebb(); +} + +int pmc56_overflow(void) +{ +	struct event event; + +	/* Use PMC2 so we set PMCjCE, which enables PMC5/6 */ +	event_init(&event, 0x2001e); +	event_leader_ebb_init(&event); + +	event.attr.exclude_kernel = 1; +	event.attr.exclude_hv = 1; +	event.attr.exclude_idle = 1; + +	FAIL_IF(event_open(&event)); + +	setup_ebb_handler(ebb_callee); +	ebb_global_enable(); + +	FAIL_IF(ebb_event_enable(&event)); + +	mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); +	mtspr(SPRN_PMC5, 0); +	mtspr(SPRN_PMC6, 0); + +	while (ebb_state.stats.ebb_count < 10) +		FAIL_IF(core_busy_loop()); + +	ebb_global_disable(); +	ebb_freeze_pmcs(); + +	count_pmc(2, sample_period); + +	dump_ebb_state(); + +	printf("PMC5/6 overflow %d\n", pmc56_overflowed); + +	event_close(&event); + +	FAIL_IF(ebb_state.stats.ebb_count == 0 || pmc56_overflowed != 0); + +	return 0; +} + +int main(void) +{ +	return test_harness(pmc56_overflow, "pmc56_overflow"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/reg.h b/tools/testing/selftests/powerpc/pmu/ebb/reg.h new file mode 100644 index 00000000000..5921b0dfe2e --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/reg.h @@ -0,0 +1,49 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#ifndef _SELFTESTS_POWERPC_REG_H +#define _SELFTESTS_POWERPC_REG_H + +#define __stringify_1(x)        #x +#define __stringify(x)          __stringify_1(x) + +#define mfspr(rn)       ({unsigned long rval; \ +                         asm volatile("mfspr %0," __stringify(rn) \ +                                 : "=r" (rval)); rval; }) +#define mtspr(rn, v)    asm volatile("mtspr " __stringify(rn) ",%0" : \ +                                    : "r" ((unsigned long)(v)) \ +                                    : "memory") + +#define mb()		asm volatile("sync" : : : "memory"); + +#define SPRN_MMCR2     769 +#define SPRN_MMCRA     770 +#define SPRN_MMCR0     779 +#define   MMCR0_PMAO   0x00000080 +#define   MMCR0_PMAE   0x04000000 +#define   MMCR0_FC     0x80000000 +#define SPRN_EBBHR     804 +#define SPRN_EBBRR     805 +#define SPRN_BESCR     806     /* Branch event status & control register */ +#define SPRN_BESCRS    800     /* Branch event status & control set (1 bits set to 1) */ +#define SPRN_BESCRSU   801     /* Branch event status & control set upper */ +#define SPRN_BESCRR    802     /* Branch event status & control REset (1 bits set to 0) */ +#define SPRN_BESCRRU   803     /* Branch event status & control REset upper */ + +#define BESCR_PMEO     0x1     /* PMU Event-based exception Occurred */ +#define BESCR_PME      (0x1ul << 32) /* PMU Event-based exception Enable */ + +#define SPRN_PMC1      771 +#define SPRN_PMC2      772 +#define SPRN_PMC3      773 +#define SPRN_PMC4      774 +#define SPRN_PMC5      775 +#define SPRN_PMC6      776 + +#define SPRN_SIAR      780 +#define SPRN_SDAR      781 +#define SPRN_SIER      768 + +#endif /* _SELFTESTS_POWERPC_REG_H */ diff --git a/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c b/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c new file mode 100644 index 00000000000..0cae66f659a --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c @@ -0,0 +1,39 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "ebb.h" +#include "reg.h" + + +/* + * Test basic access to the EBB regs, they should be user accessible with no + * kernel interaction required. + */ +int reg_access(void) +{ +	uint64_t val, expected; + +	expected = 0x8000000100000000ull; +	mtspr(SPRN_BESCR, expected); +	val = mfspr(SPRN_BESCR); + +	FAIL_IF(val != expected); + +	expected = 0x0000000001000000ull; +	mtspr(SPRN_EBBHR, expected); +	val = mfspr(SPRN_EBBHR); + +	FAIL_IF(val != expected); + +	return 0; +} + +int main(void) +{ +	return test_harness(reg_access, "reg_access"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/task_event_pinned_vs_ebb_test.c b/tools/testing/selftests/powerpc/pmu/ebb/task_event_pinned_vs_ebb_test.c new file mode 100644 index 00000000000..d56607e4ffa --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/task_event_pinned_vs_ebb_test.c @@ -0,0 +1,91 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#include "ebb.h" + + +/* + * Tests a pinned per-task event vs an EBB - in that order. The pinned per-task + * event should prevent the EBB event from being enabled. + */ + +static int setup_child_event(struct event *event, pid_t child_pid) +{ +	event_init_named(event, 0x400FA, "PM_RUN_INST_CMPL"); + +	event->attr.pinned = 1; + +	event->attr.exclude_kernel = 1; +	event->attr.exclude_hv = 1; +	event->attr.exclude_idle = 1; + +	FAIL_IF(event_open_with_pid(event, child_pid)); +	FAIL_IF(event_enable(event)); + +	return 0; +} + +int task_event_pinned_vs_ebb(void) +{ +	union pipe read_pipe, write_pipe; +	struct event event; +	pid_t pid; +	int rc; + +	FAIL_IF(pipe(read_pipe.fds) == -1); +	FAIL_IF(pipe(write_pipe.fds) == -1); + +	pid = fork(); +	if (pid == 0) { +		/* NB order of pipes looks reversed */ +		exit(ebb_child(write_pipe, read_pipe)); +	} + +	/* We setup the task event first */ +	rc = setup_child_event(&event, pid); +	if (rc) { +		kill_child_and_wait(pid); +		return rc; +	} + +	/* Signal the child to install its EBB event and wait */ +	if (sync_with_child(read_pipe, write_pipe)) +		/* If it fails, wait for it to exit */ +		goto wait; + +	/* Signal the child to run */ +	FAIL_IF(sync_with_child(read_pipe, write_pipe)); + +wait: +	/* We expect it to fail to read the event */ +	FAIL_IF(wait_for_child(pid) != 2); +	FAIL_IF(event_disable(&event)); +	FAIL_IF(event_read(&event)); + +	event_report(&event); + +	FAIL_IF(event.result.value == 0); +	/* +	 * For reasons I don't understand enabled is usually just slightly +	 * lower than running. Would be good to confirm why. +	 */ +	FAIL_IF(event.result.enabled == 0); +	FAIL_IF(event.result.running == 0); + +	return 0; +} + +int main(void) +{ +	return test_harness(task_event_pinned_vs_ebb, "task_event_pinned_vs_ebb"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/task_event_vs_ebb_test.c b/tools/testing/selftests/powerpc/pmu/ebb/task_event_vs_ebb_test.c new file mode 100644 index 00000000000..eba32196dbb --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/task_event_vs_ebb_test.c @@ -0,0 +1,83 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#include "ebb.h" + + +/* + * Tests a per-task event vs an EBB - in that order. The EBB should push the + * per-task event off the PMU. + */ + +static int setup_child_event(struct event *event, pid_t child_pid) +{ +	event_init_named(event, 0x400FA, "PM_RUN_INST_CMPL"); + +	event->attr.exclude_kernel = 1; +	event->attr.exclude_hv = 1; +	event->attr.exclude_idle = 1; + +	FAIL_IF(event_open_with_pid(event, child_pid)); +	FAIL_IF(event_enable(event)); + +	return 0; +} + +int task_event_vs_ebb(void) +{ +	union pipe read_pipe, write_pipe; +	struct event event; +	pid_t pid; +	int rc; + +	FAIL_IF(pipe(read_pipe.fds) == -1); +	FAIL_IF(pipe(write_pipe.fds) == -1); + +	pid = fork(); +	if (pid == 0) { +		/* NB order of pipes looks reversed */ +		exit(ebb_child(write_pipe, read_pipe)); +	} + +	/* We setup the task event first */ +	rc = setup_child_event(&event, pid); +	if (rc) { +		kill_child_and_wait(pid); +		return rc; +	} + +	/* Signal the child to install its EBB event and wait */ +	if (sync_with_child(read_pipe, write_pipe)) +		/* If it fails, wait for it to exit */ +		goto wait; + +	/* Signal the child to run */ +	FAIL_IF(sync_with_child(read_pipe, write_pipe)); + +wait: +	/* The EBB event should push the task event off so the child should succeed */ +	FAIL_IF(wait_for_child(pid)); +	FAIL_IF(event_disable(&event)); +	FAIL_IF(event_read(&event)); + +	event_report(&event); + +	/* The task event may have run, or not so we can't assert anything about it */ + +	return 0; +} + +int main(void) +{ +	return test_harness(task_event_vs_ebb, "task_event_vs_ebb"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/trace.c b/tools/testing/selftests/powerpc/pmu/ebb/trace.c new file mode 100644 index 00000000000..251e66ab2aa --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/trace.c @@ -0,0 +1,300 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> + +#include "trace.h" + + +struct trace_buffer *trace_buffer_allocate(u64 size) +{ +	struct trace_buffer *tb; + +	if (size < sizeof(*tb)) { +		fprintf(stderr, "Error: trace buffer too small\n"); +		return NULL; +	} + +	tb = mmap(NULL, size, PROT_READ | PROT_WRITE, +		  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); +	if (tb == MAP_FAILED) { +		perror("mmap"); +		return NULL; +	} + +	tb->size = size; +	tb->tail = tb->data; +	tb->overflow = false; + +	return tb; +} + +static bool trace_check_bounds(struct trace_buffer *tb, void *p) +{ +	return p < ((void *)tb + tb->size); +} + +static bool trace_check_alloc(struct trace_buffer *tb, void *p) +{ +	/* +	 * If we ever overflowed don't allow any more input. This prevents us +	 * from dropping a large item and then later logging a small one. The +	 * buffer should just stop when overflow happened, not be patchy. If +	 * you're overflowing, make your buffer bigger. +	 */ +	if (tb->overflow) +		return false; + +	if (!trace_check_bounds(tb, p)) { +		tb->overflow = true; +		return false; +	} + +	return true; +} + +static void *trace_alloc(struct trace_buffer *tb, int bytes) +{ +	void *p, *newtail; + +	p = tb->tail; +	newtail = tb->tail + bytes; +	if (!trace_check_alloc(tb, newtail)) +		return NULL; + +	tb->tail = newtail; + +	return p; +} + +static struct trace_entry *trace_alloc_entry(struct trace_buffer *tb, int payload_size) +{ +	struct trace_entry *e; + +	e = trace_alloc(tb, sizeof(*e) + payload_size); +	if (e) +		e->length = payload_size; + +	return e; +} + +int trace_log_reg(struct trace_buffer *tb, u64 reg, u64 value) +{ +	struct trace_entry *e; +	u64 *p; + +	e = trace_alloc_entry(tb, sizeof(reg) + sizeof(value)); +	if (!e) +		return -ENOSPC; + +	e->type = TRACE_TYPE_REG; +	p = (u64 *)e->data; +	*p++ = reg; +	*p++ = value; + +	return 0; +} + +int trace_log_counter(struct trace_buffer *tb, u64 value) +{ +	struct trace_entry *e; +	u64 *p; + +	e = trace_alloc_entry(tb, sizeof(value)); +	if (!e) +		return -ENOSPC; + +	e->type = TRACE_TYPE_COUNTER; +	p = (u64 *)e->data; +	*p++ = value; + +	return 0; +} + +int trace_log_string(struct trace_buffer *tb, char *str) +{ +	struct trace_entry *e; +	char *p; +	int len; + +	len = strlen(str); + +	/* We NULL terminate to make printing easier */ +	e = trace_alloc_entry(tb, len + 1); +	if (!e) +		return -ENOSPC; + +	e->type = TRACE_TYPE_STRING; +	p = (char *)e->data; +	memcpy(p, str, len); +	p += len; +	*p = '\0'; + +	return 0; +} + +int trace_log_indent(struct trace_buffer *tb) +{ +	struct trace_entry *e; + +	e = trace_alloc_entry(tb, 0); +	if (!e) +		return -ENOSPC; + +	e->type = TRACE_TYPE_INDENT; + +	return 0; +} + +int trace_log_outdent(struct trace_buffer *tb) +{ +	struct trace_entry *e; + +	e = trace_alloc_entry(tb, 0); +	if (!e) +		return -ENOSPC; + +	e->type = TRACE_TYPE_OUTDENT; + +	return 0; +} + +static void trace_print_header(int seq, int prefix) +{ +	printf("%*s[%d]: ", prefix, "", seq); +} + +static char *trace_decode_reg(int reg) +{ +	switch (reg) { +		case 769: return "SPRN_MMCR2"; break; +		case 770: return "SPRN_MMCRA"; break; +		case 779: return "SPRN_MMCR0"; break; +		case 804: return "SPRN_EBBHR"; break; +		case 805: return "SPRN_EBBRR"; break; +		case 806: return "SPRN_BESCR"; break; +		case 800: return "SPRN_BESCRS"; break; +		case 801: return "SPRN_BESCRSU"; break; +		case 802: return "SPRN_BESCRR"; break; +		case 803: return "SPRN_BESCRRU"; break; +		case 771: return "SPRN_PMC1"; break; +		case 772: return "SPRN_PMC2"; break; +		case 773: return "SPRN_PMC3"; break; +		case 774: return "SPRN_PMC4"; break; +		case 775: return "SPRN_PMC5"; break; +		case 776: return "SPRN_PMC6"; break; +		case 780: return "SPRN_SIAR"; break; +		case 781: return "SPRN_SDAR"; break; +		case 768: return "SPRN_SIER"; break; +	} + +	return NULL; +} + +static void trace_print_reg(struct trace_entry *e) +{ +	u64 *p, *reg, *value; +	char *name; + +	p = (u64 *)e->data; +	reg = p++; +	value = p; + +	name = trace_decode_reg(*reg); +	if (name) +		printf("register %-10s = 0x%016llx\n", name, *value); +	else +		printf("register %lld = 0x%016llx\n", *reg, *value); +} + +static void trace_print_counter(struct trace_entry *e) +{ +	u64 *value; + +	value = (u64 *)e->data; +	printf("counter = %lld\n", *value); +} + +static void trace_print_string(struct trace_entry *e) +{ +	char *str; + +	str = (char *)e->data; +	puts(str); +} + +#define BASE_PREFIX	2 +#define PREFIX_DELTA	8 + +static void trace_print_entry(struct trace_entry *e, int seq, int *prefix) +{ +	switch (e->type) { +	case TRACE_TYPE_REG: +		trace_print_header(seq, *prefix); +		trace_print_reg(e); +		break; +	case TRACE_TYPE_COUNTER: +		trace_print_header(seq, *prefix); +		trace_print_counter(e); +		break; +	case TRACE_TYPE_STRING: +		trace_print_header(seq, *prefix); +		trace_print_string(e); +		break; +	case TRACE_TYPE_INDENT: +		trace_print_header(seq, *prefix); +		puts("{"); +		*prefix += PREFIX_DELTA; +		break; +	case TRACE_TYPE_OUTDENT: +		*prefix -= PREFIX_DELTA; +		if (*prefix < BASE_PREFIX) +			*prefix = BASE_PREFIX; +		trace_print_header(seq, *prefix); +		puts("}"); +		break; +	default: +		trace_print_header(seq, *prefix); +		printf("entry @ %p type %d\n", e, e->type); +		break; +	} +} + +void trace_buffer_print(struct trace_buffer *tb) +{ +	struct trace_entry *e; +	int i, prefix; +	void *p; + +	printf("Trace buffer dump:\n"); +	printf("  address  %p \n", tb); +	printf("  tail     %p\n", tb->tail); +	printf("  size     %llu\n", tb->size); +	printf("  overflow %s\n", tb->overflow ? "TRUE" : "false"); +	printf("  Content:\n"); + +	p = tb->data; + +	i = 0; +	prefix = BASE_PREFIX; + +	while (trace_check_bounds(tb, p) && p < tb->tail) { +		e = p; + +		trace_print_entry(e, i, &prefix); + +		i++; +		p = (void *)e + sizeof(*e) + e->length; +	} +} + +void trace_print_location(struct trace_buffer *tb) +{ +	printf("Trace buffer 0x%llx bytes @ %p\n", tb->size, tb); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/trace.h b/tools/testing/selftests/powerpc/pmu/ebb/trace.h new file mode 100644 index 00000000000..926458e28c8 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/trace.h @@ -0,0 +1,41 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#ifndef _SELFTESTS_POWERPC_PMU_EBB_TRACE_H +#define _SELFTESTS_POWERPC_PMU_EBB_TRACE_H + +#include "utils.h" + +#define TRACE_TYPE_REG		1 +#define TRACE_TYPE_COUNTER	2 +#define TRACE_TYPE_STRING	3 +#define TRACE_TYPE_INDENT	4 +#define TRACE_TYPE_OUTDENT	5 + +struct trace_entry +{ +	u8 type; +	u8 length; +	u8 data[0]; +}; + +struct trace_buffer +{ +	u64  size; +	bool overflow; +	void *tail; +	u8   data[0]; +}; + +struct trace_buffer *trace_buffer_allocate(u64 size); +int trace_log_reg(struct trace_buffer *tb, u64 reg, u64 value); +int trace_log_counter(struct trace_buffer *tb, u64 value); +int trace_log_string(struct trace_buffer *tb, char *str); +int trace_log_indent(struct trace_buffer *tb); +int trace_log_outdent(struct trace_buffer *tb); +void trace_buffer_print(struct trace_buffer *tb); +void trace_print_location(struct trace_buffer *tb); + +#endif /* _SELFTESTS_POWERPC_PMU_EBB_TRACE_H */ diff --git a/tools/testing/selftests/powerpc/pmu/event.c b/tools/testing/selftests/powerpc/pmu/event.c index 2b2d11df245..184b36807d4 100644 --- a/tools/testing/selftests/powerpc/pmu/event.c +++ b/tools/testing/selftests/powerpc/pmu/event.c @@ -39,7 +39,13 @@ void event_init_named(struct event *e, u64 config, char *name)  	event_init_opts(e, config, PERF_TYPE_RAW, name);  } +void event_init(struct event *e, u64 config) +{ +	event_init_opts(e, config, PERF_TYPE_RAW, "event"); +} +  #define PERF_CURRENT_PID	0 +#define PERF_NO_PID		-1  #define PERF_NO_CPU		-1  #define PERF_NO_GROUP		-1 @@ -59,6 +65,16 @@ int event_open_with_group(struct event *e, int group_fd)  	return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, group_fd);  } +int event_open_with_pid(struct event *e, pid_t pid) +{ +	return event_open_with_options(e, pid, PERF_NO_CPU, PERF_NO_GROUP); +} + +int event_open_with_cpu(struct event *e, int cpu) +{ +	return event_open_with_options(e, PERF_NO_PID, cpu, PERF_NO_GROUP); +} +  int event_open(struct event *e)  {  	return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, PERF_NO_GROUP); @@ -69,6 +85,16 @@ void event_close(struct event *e)  	close(e->fd);  } +int event_enable(struct event *e) +{ +	return ioctl(e->fd, PERF_EVENT_IOC_ENABLE); +} + +int event_disable(struct event *e) +{ +	return ioctl(e->fd, PERF_EVENT_IOC_DISABLE); +} +  int event_reset(struct event *e)  {  	return ioctl(e->fd, PERF_EVENT_IOC_RESET); diff --git a/tools/testing/selftests/powerpc/pmu/event.h b/tools/testing/selftests/powerpc/pmu/event.h index e6993192ff3..a0ea6b1eef7 100644 --- a/tools/testing/selftests/powerpc/pmu/event.h +++ b/tools/testing/selftests/powerpc/pmu/event.h @@ -29,8 +29,12 @@ void event_init_named(struct event *e, u64 config, char *name);  void event_init_opts(struct event *e, u64 config, int type, char *name);  int event_open_with_options(struct event *e, pid_t pid, int cpu, int group_fd);  int event_open_with_group(struct event *e, int group_fd); +int event_open_with_pid(struct event *e, pid_t pid); +int event_open_with_cpu(struct event *e, int cpu);  int event_open(struct event *e);  void event_close(struct event *e); +int event_enable(struct event *e); +int event_disable(struct event *e);  int event_reset(struct event *e);  int event_read(struct event *e);  void event_report_justified(struct event *e, int name_width, int result_width); diff --git a/tools/testing/selftests/powerpc/pmu/lib.c b/tools/testing/selftests/powerpc/pmu/lib.c new file mode 100644 index 00000000000..0f6a4731d54 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/lib.c @@ -0,0 +1,252 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#define _GNU_SOURCE	/* For CPU_ZERO etc. */ + +#include <errno.h> +#include <sched.h> +#include <setjmp.h> +#include <stdlib.h> +#include <sys/wait.h> + +#include "utils.h" +#include "lib.h" + + +int pick_online_cpu(void) +{ +	cpu_set_t mask; +	int cpu; + +	CPU_ZERO(&mask); + +	if (sched_getaffinity(0, sizeof(mask), &mask)) { +		perror("sched_getaffinity"); +		return -1; +	} + +	/* We prefer a primary thread, but skip 0 */ +	for (cpu = 8; cpu < CPU_SETSIZE; cpu += 8) +		if (CPU_ISSET(cpu, &mask)) +			return cpu; + +	/* Search for anything, but in reverse */ +	for (cpu = CPU_SETSIZE - 1; cpu >= 0; cpu--) +		if (CPU_ISSET(cpu, &mask)) +			return cpu; + +	printf("No cpus in affinity mask?!\n"); +	return -1; +} + +int bind_to_cpu(int cpu) +{ +	cpu_set_t mask; + +	printf("Binding to cpu %d\n", cpu); + +	CPU_ZERO(&mask); +	CPU_SET(cpu, &mask); + +	return sched_setaffinity(0, sizeof(mask), &mask); +} + +#define PARENT_TOKEN	0xAA +#define CHILD_TOKEN	0x55 + +int sync_with_child(union pipe read_pipe, union pipe write_pipe) +{ +	char c = PARENT_TOKEN; + +	FAIL_IF(write(write_pipe.write_fd, &c, 1) != 1); +	FAIL_IF(read(read_pipe.read_fd, &c, 1) != 1); +	if (c != CHILD_TOKEN) /* sometimes expected */ +		return 1; + +	return 0; +} + +int wait_for_parent(union pipe read_pipe) +{ +	char c; + +	FAIL_IF(read(read_pipe.read_fd, &c, 1) != 1); +	FAIL_IF(c != PARENT_TOKEN); + +	return 0; +} + +int notify_parent(union pipe write_pipe) +{ +	char c = CHILD_TOKEN; + +	FAIL_IF(write(write_pipe.write_fd, &c, 1) != 1); + +	return 0; +} + +int notify_parent_of_error(union pipe write_pipe) +{ +	char c = ~CHILD_TOKEN; + +	FAIL_IF(write(write_pipe.write_fd, &c, 1) != 1); + +	return 0; +} + +int wait_for_child(pid_t child_pid) +{ +	int rc; + +	if (waitpid(child_pid, &rc, 0) == -1) { +		perror("waitpid"); +		return 1; +	} + +	if (WIFEXITED(rc)) +		rc = WEXITSTATUS(rc); +	else +		rc = 1; /* Signal or other */ + +	return rc; +} + +int kill_child_and_wait(pid_t child_pid) +{ +	kill(child_pid, SIGTERM); + +	return wait_for_child(child_pid); +} + +static int eat_cpu_child(union pipe read_pipe, union pipe write_pipe) +{ +	volatile int i = 0; + +	/* +	 * We are just here to eat cpu and die. So make sure we can be killed, +	 * and also don't do any custom SIGTERM handling. +	 */ +	signal(SIGTERM, SIG_DFL); + +	notify_parent(write_pipe); +	wait_for_parent(read_pipe); + +	/* Soak up cpu forever */ +	while (1) i++; + +	return 0; +} + +pid_t eat_cpu(int (test_function)(void)) +{ +	union pipe read_pipe, write_pipe; +	int cpu, rc; +	pid_t pid; + +	cpu = pick_online_cpu(); +	FAIL_IF(cpu < 0); +	FAIL_IF(bind_to_cpu(cpu)); + +	if (pipe(read_pipe.fds) == -1) +		return -1; + +	if (pipe(write_pipe.fds) == -1) +		return -1; + +	pid = fork(); +	if (pid == 0) +		exit(eat_cpu_child(write_pipe, read_pipe)); + +	if (sync_with_child(read_pipe, write_pipe)) { +		rc = -1; +		goto out; +	} + +	printf("main test running as pid %d\n", getpid()); + +	rc = test_function(); +out: +	kill(pid, SIGKILL); + +	return rc; +} + +struct addr_range libc, vdso; + +int parse_proc_maps(void) +{ +	char execute, name[128]; +	uint64_t start, end; +	FILE *f; +	int rc; + +	f = fopen("/proc/self/maps", "r"); +	if (!f) { +		perror("fopen"); +		return -1; +	} + +	do { +		/* This skips line with no executable which is what we want */ +		rc = fscanf(f, "%lx-%lx %*c%*c%c%*c %*x %*d:%*d %*d %127s\n", +			    &start, &end, &execute, name); +		if (rc <= 0) +			break; + +		if (execute != 'x') +			continue; + +		if (strstr(name, "libc")) { +			libc.first = start; +			libc.last = end - 1; +		} else if (strstr(name, "[vdso]")) { +			vdso.first = start; +			vdso.last = end - 1; +		} +	} while(1); + +	fclose(f); + +	return 0; +} + +#define PARANOID_PATH	"/proc/sys/kernel/perf_event_paranoid" + +bool require_paranoia_below(int level) +{ +	unsigned long current; +	char *end, buf[16]; +	FILE *f; +	int rc; + +	rc = -1; + +	f = fopen(PARANOID_PATH, "r"); +	if (!f) { +		perror("fopen"); +		goto out; +	} + +	if (!fgets(buf, sizeof(buf), f)) { +		printf("Couldn't read " PARANOID_PATH "?\n"); +		goto out_close; +	} + +	current = strtoul(buf, &end, 10); + +	if (end == buf) { +		printf("Couldn't parse " PARANOID_PATH "?\n"); +		goto out_close; +	} + +	if (current >= level) +		goto out; + +	rc = 0; +out_close: +	fclose(f); +out: +	return rc; +} diff --git a/tools/testing/selftests/powerpc/pmu/lib.h b/tools/testing/selftests/powerpc/pmu/lib.h new file mode 100644 index 00000000000..ca5d72ae3be --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/lib.h @@ -0,0 +1,41 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#ifndef __SELFTESTS_POWERPC_PMU_LIB_H +#define __SELFTESTS_POWERPC_PMU_LIB_H + +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +union pipe { +	struct { +		int read_fd; +		int write_fd; +	}; +	int fds[2]; +}; + +extern int pick_online_cpu(void); +extern int bind_to_cpu(int cpu); +extern int kill_child_and_wait(pid_t child_pid); +extern int wait_for_child(pid_t child_pid); +extern int sync_with_child(union pipe read_pipe, union pipe write_pipe); +extern int wait_for_parent(union pipe read_pipe); +extern int notify_parent(union pipe write_pipe); +extern int notify_parent_of_error(union pipe write_pipe); +extern pid_t eat_cpu(int (test_function)(void)); +extern bool require_paranoia_below(int level); + +struct addr_range { +	uint64_t first, last; +}; + +extern struct addr_range libc, vdso; + +int parse_proc_maps(void); + +#endif /* __SELFTESTS_POWERPC_PMU_LIB_H */ diff --git a/tools/testing/selftests/powerpc/pmu/loop.S b/tools/testing/selftests/powerpc/pmu/loop.S index 8820e3df144..20c1f0876c4 100644 --- a/tools/testing/selftests/powerpc/pmu/loop.S +++ b/tools/testing/selftests/powerpc/pmu/loop.S @@ -3,44 +3,41 @@   * Licensed under GPLv2.   */ +#include <ppc-asm.h> +  	.text -	.global thirty_two_instruction_loop -	.type .thirty_two_instruction_loop,@function -	.section ".opd","aw",@progbits -thirty_two_instruction_loop: -	.quad .thirty_two_instruction_loop, .TOC.@tocbase, 0 -	.previous -.thirty_two_instruction_loop: -	cmpwi	%r3,0 +FUNC_START(thirty_two_instruction_loop) +	cmpdi	r3,0  	beqlr -	addi	%r4,%r3,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1 -	addi	%r4,%r4,1	# 28 addi's -	subi	%r3,%r3,1 -	b	.thirty_two_instruction_loop +	addi	r4,r3,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1 +	addi	r4,r4,1	# 28 addi's +	subi	r3,r3,1 +	b	FUNC_NAME(thirty_two_instruction_loop) +FUNC_END(thirty_two_instruction_loop) diff --git a/tools/testing/selftests/powerpc/subunit.h b/tools/testing/selftests/powerpc/subunit.h index 98a22920792..9c6c4e901ab 100644 --- a/tools/testing/selftests/powerpc/subunit.h +++ b/tools/testing/selftests/powerpc/subunit.h @@ -26,6 +26,11 @@ static inline void test_error(char *name)  	printf("error: %s\n", name);  } +static inline void test_skip(char *name) +{ +	printf("skip: %s\n", name); +} +  static inline void test_success(char *name)  {  	printf("success: %s\n", name); diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile new file mode 100644 index 00000000000..2cede239a07 --- /dev/null +++ b/tools/testing/selftests/powerpc/tm/Makefile @@ -0,0 +1,15 @@ +PROGS := tm-resched-dscr + +all: $(PROGS) + +$(PROGS): ../harness.c + +run_tests: all +	@-for PROG in $(PROGS); do \ +		./$$PROG; \ +	done; + +clean: +	rm -f $(PROGS) *.o + +.PHONY: all run_tests clean diff --git a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c new file mode 100644 index 00000000000..42d4c8caad8 --- /dev/null +++ b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c @@ -0,0 +1,98 @@ +/* Test context switching to see if the DSCR SPR is correctly preserved + * when within a transaction. + * + * Note: We assume that the DSCR has been left at the default value (0) + * for all CPUs. + * + * Method: + * + * Set a value into the DSCR. + * + * Start a transaction, and suspend it (*). + * + * Hard loop checking to see if the transaction has become doomed. + * + * Now that we *may* have been preempted, record the DSCR and TEXASR SPRS. + * + * If the abort was because of a context switch, check the DSCR value. + * Otherwise, try again. + * + * (*) If the transaction is not suspended we can't see the problem because + * the transaction abort handler will restore the DSCR to it's checkpointed + * value before we regain control. + */ + +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <asm/tm.h> + +#include "utils.h" + +#define TBEGIN          ".long 0x7C00051D ;" +#define TEND            ".long 0x7C00055D ;" +#define TCHECK          ".long 0x7C00059C ;" +#define TSUSPEND        ".long 0x7C0005DD ;" +#define TRESUME         ".long 0x7C2005DD ;" +#define SPRN_TEXASR     0x82 +#define SPRN_DSCR       0x03 + +int test_body(void) +{ +	uint64_t rv, dscr1 = 1, dscr2, texasr; + +	printf("Check DSCR TM context switch: "); +	fflush(stdout); +	for (;;) { +		rv = 1; +		asm __volatile__ ( +			/* set a known value into the DSCR */ +			"ld      3, %[dscr1];" +			"mtspr   %[sprn_dscr], 3;" + +			/* start and suspend a transaction */ +			TBEGIN +			"beq     1f;" +			TSUSPEND + +			/* hard loop until the transaction becomes doomed */ +			"2: ;" +			TCHECK +			"bc      4, 0, 2b;" + +			/* record DSCR and TEXASR */ +			"mfspr   3, %[sprn_dscr];" +			"std     3, %[dscr2];" +			"mfspr   3, %[sprn_texasr];" +			"std     3, %[texasr];" + +			TRESUME +			TEND +			"li      %[rv], 0;" +			"1: ;" +			: [rv]"=r"(rv), [dscr2]"=m"(dscr2), [texasr]"=m"(texasr) +			: [dscr1]"m"(dscr1) +			, [sprn_dscr]"i"(SPRN_DSCR), [sprn_texasr]"i"(SPRN_TEXASR) +			: "memory", "r3" +		); +		assert(rv); /* make sure the transaction aborted */ +		if ((texasr >> 56) != TM_CAUSE_RESCHED) { +			putchar('.'); +			fflush(stdout); +			continue; +		} +		if (dscr2 != dscr1) { +			printf(" FAIL\n"); +			return 1; +		} else { +			printf(" OK\n"); +			return 0; +		} +	} +} + +int main(void) +{ +	return test_harness(test_body, "tm_resched_dscr"); +} diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h index 5851c4b0f55..a93777ae068 100644 --- a/tools/testing/selftests/powerpc/utils.h +++ b/tools/testing/selftests/powerpc/utils.h @@ -31,4 +31,19 @@ do {								\  	}							\  } while (0) +/* The test harness uses this, yes it's gross */ +#define MAGIC_SKIP_RETURN_VALUE	99 + +#define SKIP_IF(x)						\ +do {								\ +	if ((x)) {						\ +		fprintf(stderr,					\ +		"[SKIP] Test skipped on line %d\n", __LINE__);	\ +		return MAGIC_SKIP_RETURN_VALUE;			\ +	}							\ +} while (0) + +#define _str(s) #s +#define str(s) _str(s) +  #endif /* _SELFTESTS_POWERPC_UTILS_H */ diff --git a/tools/testing/selftests/rcutorture/.gitignore b/tools/testing/selftests/rcutorture/.gitignore new file mode 100644 index 00000000000..05838f6f2eb --- /dev/null +++ b/tools/testing/selftests/rcutorture/.gitignore @@ -0,0 +1,6 @@ +initrd +linux-2.6 +b[0-9]* +rcu-test-image +res +*.swp diff --git a/tools/testing/selftests/rcutorture/bin/config2frag.sh b/tools/testing/selftests/rcutorture/bin/config2frag.sh new file mode 100644 index 00000000000..9f9ffcd427d --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/config2frag.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# Usage: sh config2frag.sh < .config > configfrag +# +# Converts the "# CONFIG_XXX is not set" to "CONFIG_XXX=n" so that the +# resulting file becomes a legitimate Kconfig fragment. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2013 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +LANG=C sed -e 's/^# CONFIG_\([a-zA-Z0-9_]*\) is not set$/CONFIG_\1=n/' diff --git a/tools/testing/selftests/rcutorture/bin/configNR_CPUS.sh b/tools/testing/selftests/rcutorture/bin/configNR_CPUS.sh new file mode 100755 index 00000000000..43540f1828c --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/configNR_CPUS.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# +# Extract the number of CPUs expected from the specified Kconfig-file +# fragment by checking CONFIG_SMP and CONFIG_NR_CPUS.  If the specified +# file gives no clue, base the number on the number of idle CPUs on +# the system. +# +# Usage: configNR_CPUS.sh config-frag +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2013 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +cf=$1 +if test ! -r $cf +then +	echo Unreadable config fragment $cf 1>&2 +	exit -1 +fi +if grep -q '^CONFIG_SMP=n$' $cf +then +	echo 1 +	exit 0 +fi +if grep -q '^CONFIG_NR_CPUS=' $cf +then +	grep '^CONFIG_NR_CPUS=' $cf |  +		sed -e 's/^CONFIG_NR_CPUS=\([0-9]*\).*$/\1/' +	exit 0 +fi +cpus2use.sh diff --git a/tools/testing/selftests/rcutorture/bin/configcheck.sh b/tools/testing/selftests/rcutorture/bin/configcheck.sh new file mode 100755 index 00000000000..d686537dd55 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/configcheck.sh @@ -0,0 +1,54 @@ +#!/bin/sh +# Usage: sh configcheck.sh .config .config-template +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2011 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +T=/tmp/abat-chk-config.sh.$$ +trap 'rm -rf $T' 0 +mkdir $T + +cat $1 > $T/.config + +cat $2 | sed -e 's/\(.*\)=n/# \1 is not set/' -e 's/^#CHECK#//' | +awk	' +BEGIN	{ +		print "if grep -q \"" $0 "\" < '"$T/.config"'"; +		print "then"; +		print "\t:"; +		print "else"; +		if ($1 == "#") { +			print "\tif grep -q \"" $2 "\" < '"$T/.config"'"; +			print "\tthen"; +			print "\t\tif test \"$firsttime\" = \"\"" +			print "\t\tthen" +			print "\t\t\tfirsttime=1" +			print "\t\tfi" +			print "\t\techo \":" $2 ": improperly set\""; +			print "\telse"; +			print "\t\t:"; +			print "\tfi"; +		} else { +			print "\tif test \"$firsttime\" = \"\"" +			print "\tthen" +			print "\t\tfirsttime=1" +			print "\tfi" +			print "\techo \":" $0 ": improperly set\""; +		} +		print "fi"; +	}' | sh diff --git a/tools/testing/selftests/rcutorture/bin/configinit.sh b/tools/testing/selftests/rcutorture/bin/configinit.sh new file mode 100755 index 00000000000..9c3f3d39b93 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/configinit.sh @@ -0,0 +1,74 @@ +#!/bin/sh +# +# sh configinit.sh config-spec-file [ build output dir ] +# +# Create a .config file from the spec file.  Run from the kernel source tree. +# Exits with 0 if all went well, with 1 if all went well but the config +# did not match, and some other number for other failures. +# +# The first argument is the .config specification file, which contains +# desired settings, for example, "CONFIG_NO_HZ=y".  For best results, +# this should be a full pathname. +# +# The second argument is a optional path to a build output directory, +# for example, "O=/tmp/foo".  If this argument is omitted, the .config +# file will be generated directly in the current directory. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2013 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +T=/tmp/configinit.sh.$$ +trap 'rm -rf $T' 0 +mkdir $T + +# Capture config spec file. + +c=$1 +buildloc=$2 +builddir= +if test -n $buildloc +then +	if echo $buildloc | grep -q '^O=' +	then +		builddir=`echo $buildloc | sed -e 's/^O=//'` +		if test ! -d $builddir +		then +			mkdir $builddir +		fi +	else +		echo Bad build directory: \"$builddir\" +		exit 2 +	fi +fi + +sed -e 's/^\(CONFIG[0-9A-Z_]*\)=.*$/grep -v "^# \1" |/' < $c > $T/u.sh +sed -e 's/^\(CONFIG[0-9A-Z_]*=\).*$/grep -v \1 |/' < $c >> $T/u.sh +grep '^grep' < $T/u.sh > $T/upd.sh +echo "cat - $c" >> $T/upd.sh +make mrproper +make $buildloc distclean > $builddir/Make.distclean 2>&1 +make $buildloc $TORTURE_DEFCONFIG > $builddir/Make.defconfig.out 2>&1 +mv $builddir/.config $builddir/.config.sav +sh $T/upd.sh < $builddir/.config.sav > $builddir/.config +cp $builddir/.config $builddir/.config.new +yes '' | make $buildloc oldconfig > $builddir/Make.modconfig.out 2>&1 + +# verify new config matches specification. +configcheck.sh $builddir/.config $c + +exit 0 diff --git a/tools/testing/selftests/rcutorture/bin/cpus2use.sh b/tools/testing/selftests/rcutorture/bin/cpus2use.sh new file mode 100755 index 00000000000..abe14b7f36e --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/cpus2use.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# +# Get an estimate of how CPU-hoggy to be. +# +# Usage: cpus2use.sh +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2013 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +ncpus=`grep '^processor' /proc/cpuinfo | wc -l` +idlecpus=`mpstat | tail -1 | \ +	awk -v ncpus=$ncpus '{ print ncpus * ($7 + $12) / 100 }'` +awk -v ncpus=$ncpus -v idlecpus=$idlecpus < /dev/null ' +BEGIN { +	cpus2use = idlecpus; +	if (cpus2use < 1) +		cpus2use = 1; +	if (cpus2use < ncpus / 10) +		cpus2use = ncpus / 10; +	if (cpus2use == int(cpus2use)) +		cpus2use = int(cpus2use) +	else +		cpus2use = int(cpus2use) + 1 +	print cpus2use; +}' + diff --git a/tools/testing/selftests/rcutorture/bin/functions.sh b/tools/testing/selftests/rcutorture/bin/functions.sh new file mode 100644 index 00000000000..d01b865bb10 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/functions.sh @@ -0,0 +1,223 @@ +#!/bin/bash +# +# Shell functions for the rest of the scripts. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2013 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +# bootparam_hotplug_cpu bootparam-string +# +# Returns 1 if the specified boot-parameter string tells rcutorture to +# test CPU-hotplug operations. +bootparam_hotplug_cpu () { +	echo "$1" | grep -q "rcutorture\.onoff_" +} + +# checkarg --argname argtype $# arg mustmatch cannotmatch +# +# Checks the specified argument "arg" against the mustmatch and cannotmatch +# patterns. +checkarg () { +	if test $3 -le 1 +	then +		echo $1 needs argument $2 matching \"$5\" +		usage +	fi +	if echo "$4" | grep -q -e "$5" +	then +		: +	else +		echo $1 $2 \"$4\" must match \"$5\" +		usage +	fi +	if echo "$4" | grep -q -e "$6" +	then +		echo $1 $2 \"$4\" must not match \"$6\" +		usage +	fi +} + +# configfrag_boot_params bootparam-string config-fragment-file +# +# Adds boot parameters from the .boot file, if any. +configfrag_boot_params () { +	if test -r "$2.boot" +	then +		echo $1 `grep -v '^#' "$2.boot" | tr '\012' ' '` +	else +		echo $1 +	fi +} + +# configfrag_hotplug_cpu config-fragment-file +# +# Returns 1 if the config fragment specifies hotplug CPU. +configfrag_hotplug_cpu () { +	if test ! -r "$1" +	then +		echo Unreadable config fragment "$1" 1>&2 +		exit -1 +	fi +	grep -q '^CONFIG_HOTPLUG_CPU=y$' "$1" +} + +# identify_boot_image qemu-cmd +# +# Returns the relative path to the kernel build image.  This will be +# arch/<arch>/boot/bzImage unless overridden with the TORTURE_BOOT_IMAGE +# environment variable. +identify_boot_image () { +	if test -n "$TORTURE_BOOT_IMAGE" +	then +		echo $TORTURE_BOOT_IMAGE +	else +		case "$1" in +		qemu-system-x86_64|qemu-system-i386) +			echo arch/x86/boot/bzImage +			;; +		qemu-system-ppc64) +			echo arch/powerpc/boot/bzImage +			;; +		*) +			echo "" +			;; +		esac +	fi +} + +# identify_qemu builddir +# +# Returns our best guess as to which qemu command is appropriate for +# the kernel at hand.  Override with the TORTURE_QEMU_CMD environment variable. +identify_qemu () { +	local u="`file "$1"`" +	if test -n "$TORTURE_QEMU_CMD" +	then +		echo $TORTURE_QEMU_CMD +	elif echo $u | grep -q x86-64 +	then +		echo qemu-system-x86_64 +	elif echo $u | grep -q "Intel 80386" +	then +		echo qemu-system-i386 +	elif uname -a | grep -q ppc64 +	then +		echo qemu-system-ppc64 +	else +		echo Cannot figure out what qemu command to use! 1>&2 +		echo file $1 output: $u +		# Usually this will be one of /usr/bin/qemu-system-* +		# Use TORTURE_QEMU_CMD environment variable or appropriate +		# argument to top-level script. +		exit 1 +	fi +} + +# identify_qemu_append qemu-cmd +# +# Output arguments for the qemu "-append" string based on CPU type +# and the TORTURE_QEMU_INTERACTIVE environment variable. +identify_qemu_append () { +	case "$1" in +	qemu-system-x86_64|qemu-system-i386) +		echo noapic selinux=0 initcall_debug debug +		;; +	esac +	if test -n "$TORTURE_QEMU_INTERACTIVE" +	then +		echo root=/dev/sda +	else +		echo console=ttyS0 +	fi +} + +# identify_qemu_args qemu-cmd serial-file +# +# Output arguments for qemu arguments based on the TORTURE_QEMU_MAC +# and TORTURE_QEMU_INTERACTIVE environment variables. +identify_qemu_args () { +	case "$1" in +	qemu-system-x86_64|qemu-system-i386) +		;; +	qemu-system-ppc64) +		echo -enable-kvm -M pseries -cpu POWER7 -nodefaults +		echo -device spapr-vscsi +		if test -n "$TORTURE_QEMU_INTERACTIVE" -a -n "$TORTURE_QEMU_MAC" +		then +			echo -device spapr-vlan,netdev=net0,mac=$TORTURE_QEMU_MAC +			echo -netdev bridge,br=br0,id=net0 +		elif test -n "$TORTURE_QEMU_INTERACTIVE" +		then +			echo -net nic -net user +		fi +		;; +	esac +	if test -n "$TORTURE_QEMU_INTERACTIVE" +	then +		echo -monitor stdio -serial pty -S +	else +		echo -serial file:$2 +	fi +} + +# identify_qemu_vcpus +# +# Returns the number of virtual CPUs available to the aggregate of the +# guest OSes. +identify_qemu_vcpus () { +	lscpu | grep '^CPU(s):' | sed -e 's/CPU(s)://' +} + +# print_bug +# +# Prints "BUG: " in red followed by remaining arguments +print_bug () { +	printf '\033[031mBUG: \033[m' +	echo $* +} + +# print_warning +# +# Prints "WARNING: " in yellow followed by remaining arguments +print_warning () { +	printf '\033[033mWARNING: \033[m' +	echo $* +} + +# specify_qemu_cpus qemu-cmd qemu-args #cpus +# +# Appends a string containing "-smp XXX" to qemu-args, unless the incoming +# qemu-args already contains "-smp". +specify_qemu_cpus () { +	local nt; + +	if echo $2 | grep -q -e -smp +	then +		echo $2 +	else +		case "$1" in +		qemu-system-x86_64|qemu-system-i386) +			echo $2 -smp $3 +			;; +		qemu-system-ppc64) +			nt="`lscpu | grep '^NUMA node0' | sed -e 's/^[^,]*,\([0-9]*\),.*$/\1/'`" +			echo $2 -smp cores=`expr \( $3 + $nt - 1 \) / $nt`,threads=$nt +			;; +		esac +	fi +} diff --git a/tools/testing/selftests/rcutorture/bin/kvm-build.sh b/tools/testing/selftests/rcutorture/bin/kvm-build.sh new file mode 100755 index 00000000000..7c1e56b46de --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/kvm-build.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# +# Build a kvm-ready Linux kernel from the tree in the current directory. +# +# Usage: sh kvm-build.sh config-template build-dir more-configs +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2011 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +config_template=${1} +if test -z "$config_template" -o ! -f "$config_template" -o ! -r "$config_template" +then +	echo "kvm-build.sh :$config_template: Not a readable file" +	exit 1 +fi +builddir=${2} +if test -z "$builddir" -o ! -d "$builddir" -o ! -w "$builddir" +then +	echo "kvm-build.sh :$builddir: Not a writable directory, cannot build into it" +	exit 1 +fi +moreconfigs=${3} +if test -z "$moreconfigs" -o ! -r "$moreconfigs" +then +	echo "kvm-build.sh :$moreconfigs: Not a readable file" +	exit 1 +fi + +T=/tmp/test-linux.sh.$$ +trap 'rm -rf $T' 0 +mkdir $T + +grep -v 'CONFIG_[A-Z]*_TORTURE_TEST' < ${config_template} > $T/config +cat << ___EOF___ >> $T/config +CONFIG_INITRAMFS_SOURCE="$TORTURE_INITRD" +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_CONSOLE=y +___EOF___ +cat $moreconfigs >> $T/config + +configinit.sh $T/config O=$builddir +retval=$? +if test $retval -gt 1 +then +	exit 2 +fi +ncpus=`cpus2use.sh` +make O=$builddir -j$ncpus $TORTURE_KMAKE_ARG > $builddir/Make.out 2>&1 +retval=$? +if test $retval -ne 0 || grep "rcu[^/]*": < $builddir/Make.out | egrep -q "Stop|Error|error:|warning:" || egrep -q "Stop|Error|error:" < $builddir/Make.out +then +	echo Kernel build error +	egrep "Stop|Error|error:|warning:" < $builddir/Make.out +	echo Run aborted. +	exit 3 +fi diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh new file mode 100755 index 00000000000..7f1ff1a8fc4 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# +# Analyze a given results directory for locktorture progress. +# +# Usage: sh kvm-recheck-lock.sh resdir +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2014 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +i="$1" +if test -d $i +then +	: +else +	echo Unreadable results directory: $i +	exit 1 +fi + +configfile=`echo $i | sed -e 's/^.*\///'` +ncs=`grep "Writes:  Total:" $i/console.log 2> /dev/null | tail -1 | sed -e 's/^.* Total: //' -e 's/ .*$//'` +if test -z "$ncs" +then +	echo "$configfile -------" +else +	title="$configfile ------- $ncs acquisitions/releases" +	dur=`sed -e 's/^.* locktorture.shutdown_secs=//' -e 's/ .*$//' < $i/qemu-cmd 2> /dev/null` +	if test -z "$dur" +	then +		: +	else +		ncsps=`awk -v ncs=$ncs -v dur=$dur ' +			BEGIN { print ncs / dur }' < /dev/null` +		title="$title ($ncsps per second)" +	fi +	echo $title +fi diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh new file mode 100755 index 00000000000..307c4b95f32 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# +# Analyze a given results directory for rcutorture progress. +# +# Usage: sh kvm-recheck-rcu.sh resdir +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2014 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +i="$1" +if test -d $i +then +	: +else +	echo Unreadable results directory: $i +	exit 1 +fi + +configfile=`echo $i | sed -e 's/^.*\///'` +ngps=`grep ver: $i/console.log 2> /dev/null | tail -1 | sed -e 's/^.* ver: //' -e 's/ .*$//'` +if test -z "$ngps" +then +	echo "$configfile -------" +else +	title="$configfile ------- $ngps grace periods" +	dur=`sed -e 's/^.* rcutorture.shutdown_secs=//' -e 's/ .*$//' < $i/qemu-cmd 2> /dev/null` +	if test -z "$dur" +	then +		: +	else +		ngpsps=`awk -v ngps=$ngps -v dur=$dur ' +			BEGIN { print ngps / dur }' < /dev/null` +		title="$title ($ngpsps per second)" +	fi +	echo $title +fi diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh new file mode 100755 index 00000000000..ee1f6cae3d7 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh @@ -0,0 +1,63 @@ +#!/bin/bash +# +# Given the results directories for previous KVM-based torture runs, +# check the build and console output for errors.  Given a directory +# containing results directories, this recursively checks them all. +# +# Usage: sh kvm-recheck.sh resdir ... +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2011 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +PATH=`pwd`/tools/testing/selftests/rcutorture/bin:$PATH; export PATH +. tools/testing/selftests/rcutorture/bin/functions.sh +for rd in "$@" +do +	firsttime=1 +	dirs=`find $rd -name Make.defconfig.out -print | sort | sed -e 's,/[^/]*$,,' | sort -u` +	for i in $dirs +	do +		if test -n "$firsttime" +		then +			firsttime="" +			resdir=`echo $i | sed -e 's,/$,,' -e 's,/[^/]*$,,'` +			head -1 $resdir/log +		fi +		TORTURE_SUITE="`cat $i/../TORTURE_SUITE`" +		kvm-recheck-${TORTURE_SUITE}.sh $i +		if test -f "$i/console.log" +		then +			configcheck.sh $i/.config $i/ConfigFragment +			parse-build.sh $i/Make.out $configfile +			parse-torture.sh $i/console.log $configfile +			parse-console.sh $i/console.log $configfile +			if test -r $i/Warnings +			then +				cat $i/Warnings +			fi +		else +			if test -f "$i/qemu-cmd" +			then +				print_bug qemu failed +			else +				print_bug Build failed +			fi +			echo "   $i" +		fi +	done +done diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh new file mode 100755 index 00000000000..27e544e2951 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh @@ -0,0 +1,222 @@ +#!/bin/bash +# +# Run a kvm-based test of the specified tree on the specified configs. +# Fully automated run and error checking, no graphics console. +# +# Execute this in the source tree.  Do not run it as a background task +# because qemu does not seem to like that much. +# +# Usage: sh kvm-test-1-run.sh config builddir resdir minutes qemu-args boot_args +# +# qemu-args defaults to "-nographic", along with arguments specifying the +#			number of CPUs and other options generated from +#			the underlying CPU architecture. +# boot_args defaults to value returned by the per_version_boot_params +#			shell function. +# +# Anything you specify for either qemu-args or boot_args is appended to +# the default values.  The "-smp" value is deduced from the contents of +# the config fragment. +# +# More sophisticated argument parsing is clearly needed. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2011 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +grace=120 + +T=/tmp/kvm-test-1-run.sh.$$ +trap 'rm -rf $T' 0 + +. $KVM/bin/functions.sh +. $KVPATH/ver_functions.sh + +config_template=${1} +config_dir=`echo $config_template | sed -e 's,/[^/]*$,,'` +title=`echo $config_template | sed -e 's/^.*\///'` +builddir=${2} +if test -z "$builddir" -o ! -d "$builddir" -o ! -w "$builddir" +then +	echo "kvm-test-1-run.sh :$builddir: Not a writable directory, cannot build into it" +	exit 1 +fi +resdir=${3} +if test -z "$resdir" -o ! -d "$resdir" -o ! -w "$resdir" +then +	echo "kvm-test-1-run.sh :$resdir: Not a writable directory, cannot store results into it" +	exit 1 +fi +cp $config_template $resdir/ConfigFragment +echo ' ---' `date`: Starting build +echo ' ---' Kconfig fragment at: $config_template >> $resdir/log +if test -r "$config_dir/CFcommon" +then +	cat < $config_dir/CFcommon >> $T +fi +# Optimizations below this point +# CONFIG_USB=n +# CONFIG_SECURITY=n +# CONFIG_NFS_FS=n +# CONFIG_SOUND=n +# CONFIG_INPUT_JOYSTICK=n +# CONFIG_INPUT_TABLET=n +# CONFIG_INPUT_TOUCHSCREEN=n +# CONFIG_INPUT_MISC=n +# CONFIG_INPUT_MOUSE=n +# # CONFIG_NET=n # disables console access, so accept the slower build. +# CONFIG_SCSI=n +# CONFIG_ATA=n +# CONFIG_FAT_FS=n +# CONFIG_MSDOS_FS=n +# CONFIG_VFAT_FS=n +# CONFIG_ISO9660_FS=n +# CONFIG_QUOTA=n +# CONFIG_HID=n +# CONFIG_CRYPTO=n +# CONFIG_PCCARD=n +# CONFIG_PCMCIA=n +# CONFIG_CARDBUS=n +# CONFIG_YENTA=n +if kvm-build.sh $config_template $builddir $T +then +	QEMU="`identify_qemu $builddir/vmlinux`" +	BOOT_IMAGE="`identify_boot_image $QEMU`" +	cp $builddir/Make*.out $resdir +	cp $builddir/.config $resdir +	if test -n "$BOOT_IMAGE" +	then +		cp $builddir/$BOOT_IMAGE $resdir +	else +		echo No identifiable boot image, not running KVM, see $resdir. +		echo Do the torture scripts know about your architecture? +	fi +	parse-build.sh $resdir/Make.out $title +	if test -f $builddir.wait +	then +		mv $builddir.wait $builddir.ready +	fi +else +	cp $builddir/Make*.out $resdir +	cp $builddir/.config $resdir || : +	echo Build failed, not running KVM, see $resdir. +	if test -f $builddir.wait +	then +		mv $builddir.wait $builddir.ready +	fi +	exit 1 +fi +while test -f $builddir.ready +do +	sleep 1 +done +minutes=$4 +seconds=$(($minutes * 60)) +qemu_args=$5 +boot_args=$6 + +cd $KVM +kstarttime=`awk 'BEGIN { print systime() }' < /dev/null` +echo ' ---' `date`: Starting kernel + +# Generate -smp qemu argument. +qemu_args="-nographic $qemu_args" +cpu_count=`configNR_CPUS.sh $config_template` +vcpus=`identify_qemu_vcpus` +if test $cpu_count -gt $vcpus +then +	echo CPU count limited from $cpu_count to $vcpus +	touch $resdir/Warnings +	echo CPU count limited from $cpu_count to $vcpus >> $resdir/Warnings +	cpu_count=$vcpus +fi +qemu_args="`specify_qemu_cpus "$QEMU" "$qemu_args" "$cpu_count"`" + +# Generate architecture-specific and interaction-specific qemu arguments +qemu_args="$qemu_args `identify_qemu_args "$QEMU" "$builddir/console.log"`" + +# Generate qemu -append arguments +qemu_append="`identify_qemu_append "$QEMU"`" + +# Pull in Kconfig-fragment boot parameters +boot_args="`configfrag_boot_params "$boot_args" "$config_template"`" +# Generate kernel-version-specific boot parameters +boot_args="`per_version_boot_params "$boot_args" $builddir/.config $seconds`" + +echo $QEMU $qemu_args -m 512 -kernel $builddir/$BOOT_IMAGE -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd +if test -n "$TORTURE_BUILDONLY" +then +	echo Build-only run specified, boot/test omitted. +	exit 0 +fi +( $QEMU $qemu_args -m 512 -kernel $builddir/$BOOT_IMAGE -append "$qemu_append $boot_args"; echo $? > $resdir/qemu-retval ) & +qemu_pid=$! +commandcompleted=0 +echo Monitoring qemu job at pid $qemu_pid +while : +do +	kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }' < /dev/null` +	if kill -0 $qemu_pid > /dev/null 2>&1 +	then +		if test $kruntime -ge $seconds +		then +			break; +		fi +		sleep 1 +	else +		commandcompleted=1 +		if test $kruntime -lt $seconds +		then +			echo Completed in $kruntime vs. $seconds >> $resdir/Warnings 2>&1 +			grep "^(qemu) qemu:" $resdir/kvm-test-1-run.sh.out >> $resdir/Warnings 2>&1 +			killpid="`sed -n "s/^(qemu) qemu: terminating on signal [0-9]* from pid \([0-9]*\).*$/\1/p" $resdir/Warnings`" +			if test -n "$killpid" +			then +				echo "ps -fp $killpid" >> $resdir/Warnings 2>&1 +				ps -fp $killpid >> $resdir/Warnings 2>&1 +			fi +		else +			echo ' ---' `date`: Kernel done +		fi +		break +	fi +done +if test $commandcompleted -eq 0 +then +	echo Grace period for qemu job at pid $qemu_pid +	while : +	do +		kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }' < /dev/null` +		if kill -0 $qemu_pid > /dev/null 2>&1 +		then +			: +		else +			break +		fi +		if test $kruntime -ge $((seconds + grace)) +		then +			echo "!!! Hang at $kruntime vs. $seconds seconds" >> $resdir/Warnings 2>&1 +			kill -KILL $qemu_pid +			break +		fi +		sleep 1 +	done +fi + +cp $builddir/console.log $resdir +parse-torture.sh $resdir/console.log $title +parse-console.sh $resdir/console.log $title diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh new file mode 100644 index 00000000000..40285c58653 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/kvm.sh @@ -0,0 +1,410 @@ +#!/bin/bash +# +# Run a series of 14 tests under KVM.  These are not particularly +# well-selected or well-tuned, but are the current set.  Run from the +# top level of the source tree. +# +# Edit the definitions below to set the locations of the various directories, +# as well as the test duration. +# +# Usage: sh kvm.sh [ options ] +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2011 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +scriptname=$0 +args="$*" + +T=/tmp/kvm.sh.$$ +trap 'rm -rf $T' 0 +mkdir $T + +dur=30 +dryrun="" +KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM +PATH=${KVM}/bin:$PATH; export PATH +TORTURE_DEFCONFIG=defconfig +TORTURE_BOOT_IMAGE="" +TORTURE_INITRD="$KVM/initrd"; export TORTURE_INITRD +TORTURE_KMAKE_ARG="" +TORTURE_SUITE=rcu +resdir="" +configs="" +cpus=0 +ds=`date +%Y.%m.%d-%H:%M:%S` +kversion="" + +. functions.sh + +usage () { +	echo "Usage: $scriptname optional arguments:" +	echo "       --bootargs kernel-boot-arguments" +	echo "       --bootimage relative-path-to-kernel-boot-image" +	echo "       --buildonly" +	echo "       --configs \"config-file list\"" +	echo "       --cpus N" +	echo "       --datestamp string" +	echo "       --defconfig string" +	echo "       --dryrun sched|script" +	echo "       --duration minutes" +	echo "       --interactive" +	echo "       --kmake-arg kernel-make-arguments" +	echo "       --kversion vN.NN" +	echo "       --mac nn:nn:nn:nn:nn:nn" +	echo "       --no-initrd" +	echo "       --qemu-args qemu-system-..." +	echo "       --qemu-cmd qemu-system-..." +	echo "       --results absolute-pathname" +	echo "       --torture rcu" +	exit 1 +} + +while test $# -gt 0 +do +	case "$1" in +	--bootargs) +		checkarg --bootargs "(list of kernel boot arguments)" "$#" "$2" '.*' '^--' +		TORTURE_BOOTARGS="$2" +		shift +		;; +	--bootimage) +		checkarg --bootimage "(relative path to kernel boot image)" "$#" "$2" '[a-zA-Z0-9][a-zA-Z0-9_]*' '^--' +		TORTURE_BOOT_IMAGE="$2" +		shift +		;; +	--buildonly) +		TORTURE_BUILDONLY=1 +		;; +	--configs) +		checkarg --configs "(list of config files)" "$#" "$2" '^[^/]*$' '^--' +		configs="$2" +		shift +		;; +	--cpus) +		checkarg --cpus "(number)" "$#" "$2" '^[0-9]*$' '^--' +		cpus=$2 +		shift +		;; +	--datestamp) +		checkarg --datestamp "(relative pathname)" "$#" "$2" '^[^/]*$' '^--' +		ds=$2 +		shift +		;; +	--defconfig) +		checkarg --defconfig "defconfigtype" "$#" "$2" '^[^/][^/]*$' '^--' +		TORTURE_DEFCONFIG=$2 +		shift +		;; +	--dryrun) +		checkarg --dryrun "sched|script" $# "$2" 'sched\|script' '^--' +		dryrun=$2 +		shift +		;; +	--duration) +		checkarg --duration "(minutes)" $# "$2" '^[0-9]*$' '^error' +		dur=$2 +		shift +		;; +	--interactive) +		TORTURE_QEMU_INTERACTIVE=1; export TORTURE_QEMU_INTERACTIVE +		;; +	--kmake-arg) +		checkarg --kmake-arg "(kernel make arguments)" $# "$2" '.*' '^error$' +		TORTURE_KMAKE_ARG="$2" +		shift +		;; +	--kversion) +		checkarg --kversion "(kernel version)" $# "$2" '^v[0-9.]*$' '^error' +		kversion=$2 +		shift +		;; +	--mac) +		checkarg --mac "(MAC address)" $# "$2" '^\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}$' error +		TORTURE_QEMU_MAC=$2 +		shift +		;; +	--no-initrd) +		TORTURE_INITRD=""; export TORTURE_INITRD +		;; +	--qemu-args) +		checkarg --qemu-args "-qemu args" $# "$2" '^-' '^error' +		TORTURE_QEMU_ARG="$2" +		shift +		;; +	--qemu-cmd) +		checkarg --qemu-cmd "(qemu-system-...)" $# "$2" 'qemu-system-' '^--' +		TORTURE_QEMU_CMD="$2" +		shift +		;; +	--results) +		checkarg --results "(absolute pathname)" "$#" "$2" '^/' '^error' +		resdir=$2 +		shift +		;; +	--torture) +		checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\)$' '^--' +		TORTURE_SUITE=$2 +		shift +		;; +	*) +		echo Unknown argument $1 +		usage +		;; +	esac +	shift +done + +CONFIGFRAG=${KVM}/configs/${TORTURE_SUITE}; export CONFIGFRAG +KVPATH=${CONFIGFRAG}/$kversion; export KVPATH + +if test -z "$configs" +then +	configs="`cat $CONFIGFRAG/$kversion/CFLIST`" +fi + +if test -z "$resdir" +then +	resdir=$KVM/res +fi + +# Create a file of test-name/#cpus pairs, sorted by decreasing #cpus. +touch $T/cfgcpu +for CF in $configs +do +	if test -f "$CONFIGFRAG/$kversion/$CF" +	then +		echo $CF `configNR_CPUS.sh $CONFIGFRAG/$kversion/$CF` >> $T/cfgcpu +	else +		echo "The --configs file $CF does not exist, terminating." +		exit 1 +	fi +done +sort -k2nr $T/cfgcpu > $T/cfgcpu.sort + +# Use a greedy bin-packing algorithm, sorting the list accordingly. +awk < $T/cfgcpu.sort > $T/cfgcpu.pack -v ncpus=$cpus ' +BEGIN { +	njobs = 0; +} + +{ +	# Read file of tests and corresponding required numbers of CPUs. +	cf[njobs] = $1; +	cpus[njobs] = $2; +	njobs++; +} + +END { +	alldone = 0; +	batch = 0; +	nc = -1; + +	# Each pass through the following loop creates on test batch +	# that can be executed concurrently given ncpus.  Note that a +	# given test that requires more than the available CPUs will run in +	# their own batch.  Such tests just have to make do with what +	# is available. +	while (nc != ncpus) { +		batch++; +		nc = ncpus; + +		# Each pass through the following loop considers one +		# test for inclusion in the current batch. +		for (i = 0; i < njobs; i++) { +			if (done[i]) +				continue; # Already part of a batch. +			if (nc >= cpus[i] || nc == ncpus) { + +				# This test fits into the current batch. +				done[i] = batch; +				nc -= cpus[i]; +				if (nc <= 0) +					break; # Too-big test in its own batch. +			} +		} +	} + +	# Dump out the tests in batch order. +	for (b = 1; b <= batch; b++) +		for (i = 0; i < njobs; i++) +			if (done[i] == b) +				print cf[i], cpus[i]; +}' + +# Generate a script to execute the tests in appropriate batches. +cat << ___EOF___ > $T/script +CONFIGFRAG="$CONFIGFRAG"; export CONFIGFRAG +KVM="$KVM"; export KVM +KVPATH="$KVPATH"; export KVPATH +PATH="$PATH"; export PATH +TORTURE_BOOT_IMAGE="$TORTURE_BOOT_IMAGE"; export TORTURE_BOOT_IMAGE +TORTURE_BUILDONLY="$TORTURE_BUILDONLY"; export TORTURE_BUILDONLY +TORTURE_DEFCONFIG="$TORTURE_DEFCONFIG"; export TORTURE_DEFCONFIG +TORTURE_INITRD="$TORTURE_INITRD"; export TORTURE_INITRD +TORTURE_KMAKE_ARG="$TORTURE_KMAKE_ARG"; export TORTURE_KMAKE_ARG +TORTURE_QEMU_CMD="$TORTURE_QEMU_CMD"; export TORTURE_QEMU_CMD +TORTURE_QEMU_INTERACTIVE="$TORTURE_QEMU_INTERACTIVE"; export TORTURE_QEMU_INTERACTIVE +TORTURE_QEMU_MAC="$TORTURE_QEMU_MAC"; export TORTURE_QEMU_MAC +TORTURE_SUITE="$TORTURE_SUITE"; export TORTURE_SUITE +if ! test -e $resdir +then +	mkdir -p "$resdir" || : +fi +mkdir $resdir/$ds +echo Results directory: $resdir/$ds +echo $scriptname $args +touch $resdir/$ds/log +echo $scriptname $args >> $resdir/$ds/log +echo ${TORTURE_SUITE} > $resdir/$ds/TORTURE_SUITE +pwd > $resdir/$ds/testid.txt +if test -d .git +then +	git status >> $resdir/$ds/testid.txt +	git rev-parse HEAD >> $resdir/$ds/testid.txt +	if ! git diff HEAD > $T/git-diff 2>&1 +	then +		cp $T/git-diff $resdir/$ds +	fi +fi +___EOF___ +awk < $T/cfgcpu.pack \ +	-v CONFIGDIR="$CONFIGFRAG/$kversion/" \ +	-v KVM="$KVM" \ +	-v ncpus=$cpus \ +	-v rd=$resdir/$ds/ \ +	-v dur=$dur \ +	-v TORTURE_QEMU_ARG="$TORTURE_QEMU_ARG" \ +	-v TORTURE_BOOTARGS="$TORTURE_BOOTARGS" \ +'BEGIN { +	i = 0; +} + +{ +	cf[i] = $1; +	cpus[i] = $2; +	i++; +} + +# Dump out the scripting required to run one test batch. +function dump(first, pastlast) +{ +	print "echo ----Start batch: `date`"; +	print "echo ----Start batch: `date` >> " rd "/log"; +	jn=1 +	for (j = first; j < pastlast; j++) { +		builddir=KVM "/b" jn +		cpusr[jn] = cpus[j]; +		if (cfrep[cf[j]] == "") { +			cfr[jn] = cf[j]; +			cfrep[cf[j]] = 1; +		} else { +			cfrep[cf[j]]++; +			cfr[jn] = cf[j] "." cfrep[cf[j]]; +		} +		if (cpusr[jn] > ncpus && ncpus != 0) +			ovf = "(!)"; +		else +			ovf = ""; +		print "echo ", cfr[jn], cpusr[jn] ovf ": Starting build. `date`"; +		print "echo ", cfr[jn], cpusr[jn] ovf ": Starting build. `date` >> " rd "/log"; +		print "rm -f " builddir ".*"; +		print "touch " builddir ".wait"; +		print "mkdir " builddir " > /dev/null 2>&1 || :"; +		print "mkdir " rd cfr[jn] " || :"; +		print "kvm-test-1-run.sh " CONFIGDIR cf[j], builddir, rd cfr[jn], dur " \"" TORTURE_QEMU_ARG "\" \"" TORTURE_BOOTARGS "\" > " rd cfr[jn]  "/kvm-test-1-run.sh.out 2>&1 &" +		print "echo ", cfr[jn], cpusr[jn] ovf ": Waiting for build to complete. `date`"; +		print "echo ", cfr[jn], cpusr[jn] ovf ": Waiting for build to complete. `date` >> " rd "/log"; +		print "while test -f " builddir ".wait" +		print "do" +		print "\tsleep 1" +		print "done" +		print "echo ", cfr[jn], cpusr[jn] ovf ": Build complete. `date`"; +		print "echo ", cfr[jn], cpusr[jn] ovf ": Build complete. `date` >> " rd "/log"; +		jn++; +	} +	for (j = 1; j < jn; j++) { +		builddir=KVM "/b" j +		print "rm -f " builddir ".ready" +		print "echo ----", cfr[j], cpusr[j] ovf ": Starting kernel. `date`"; +		print "echo ----", cfr[j], cpusr[j] ovf ": Starting kernel. `date` >> " rd "/log"; +	} +	print "wait" +	print "echo ---- All kernel runs complete. `date`"; +	print "echo ---- All kernel runs complete. `date` >> " rd "/log"; +	for (j = 1; j < jn; j++) { +		builddir=KVM "/b" j +		print "echo ----", cfr[j], cpusr[j] ovf ": Build/run results:"; +		print "echo ----", cfr[j], cpusr[j] ovf ": Build/run results: >> " rd "/log"; +		print "cat " rd cfr[j]  "/kvm-test-1-run.sh.out"; +		print "cat " rd cfr[j]  "/kvm-test-1-run.sh.out >> " rd "/log"; +	} +} + +END { +	njobs = i; +	nc = ncpus; +	first = 0; + +	# Each pass through the following loop considers one test. +	for (i = 0; i < njobs; i++) { +		if (ncpus == 0) { +			# Sequential test specified, each test its own batch. +			dump(i, i + 1); +			first = i; +		} else if (nc < cpus[i] && i != 0) { +			# Out of CPUs, dump out a batch. +			dump(first, i); +			first = i; +			nc = ncpus; +		} +		# Account for the CPUs needed by the current test. +		nc -= cpus[i]; +	} +	# Dump the last batch. +	if (ncpus != 0) +		dump(first, i); +}' >> $T/script + +cat << ___EOF___ >> $T/script +echo +echo +echo " --- `date` Test summary:" +echo Results directory: $resdir/$ds +if test -z "$TORTURE_BUILDONLY" +then +	kvm-recheck.sh $resdir/$ds +fi +___EOF___ + +if test "$dryrun" = script +then +	cat $T/script +	exit 0 +elif test "$dryrun" = sched +then +	# Extract the test run schedule from the script. +	egrep 'Start batch|Starting build\.' $T/script | +		grep -v ">>" | +		sed -e 's/:.*$//' -e 's/^echo //' +	exit 0 +else +	# Not a dryru, so run the script. +	sh $T/script +fi + +# Tracing: trace_event=rcu:rcu_grace_period,rcu:rcu_future_grace_period,rcu:rcu_grace_period_init,rcu:rcu_nocb_wake,rcu:rcu_preempt_task,rcu:rcu_unlock_preempted_task,rcu:rcu_quiescent_state_report,rcu:rcu_fqs,rcu:rcu_callback,rcu:rcu_kfree_callback,rcu:rcu_batch_start,rcu:rcu_invoke_callback,rcu:rcu_invoke_kfree_callback,rcu:rcu_batch_end,rcu:rcu_torture_read,rcu:rcu_barrier diff --git a/tools/testing/selftests/rcutorture/bin/parse-build.sh b/tools/testing/selftests/rcutorture/bin/parse-build.sh new file mode 100755 index 00000000000..543230951c3 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/parse-build.sh @@ -0,0 +1,57 @@ +#!/bin/sh +# +# Check the build output from an rcutorture run for goodness. +# The "file" is a pathname on the local system, and "title" is +# a text string for error-message purposes. +# +# The file must contain kernel build output. +# +# Usage: +#	sh parse-build.sh file title +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2011 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +T=$1 +title=$2 + +. functions.sh + +if grep -q CC < $T +then +	: +else +	print_bug $title no build +	exit 1 +fi + +if grep -q "error:" < $T +then +	print_bug $title build errors: +	grep "error:" < $T +	exit 2 +fi +exit 0 + +if egrep -q "rcu[^/]*\.c.*warning:|rcu.*\.h.*warning:" < $T +then +	print_warning $title build errors: +	egrep "rcu[^/]*\.c.*warning:|rcu.*\.h.*warning:" < $T +	exit 2 +fi +exit 0 diff --git a/tools/testing/selftests/rcutorture/bin/parse-console.sh b/tools/testing/selftests/rcutorture/bin/parse-console.sh new file mode 100755 index 00000000000..4185d4cab32 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/parse-console.sh @@ -0,0 +1,41 @@ +#!/bin/sh +# +# Check the console output from an rcutorture run for oopses. +# The "file" is a pathname on the local system, and "title" is +# a text string for error-message purposes. +# +# Usage: +#	sh parse-console.sh file title +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2011 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +T=/tmp/abat-chk-badness.sh.$$ +trap 'rm -f $T' 0 + +file="$1" +title="$2" + +. functions.sh + +egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $T +if test -s $T +then +	print_warning Assertion failure in $file $title +	cat $T +fi diff --git a/tools/testing/selftests/rcutorture/bin/parse-torture.sh b/tools/testing/selftests/rcutorture/bin/parse-torture.sh new file mode 100755 index 00000000000..3455560ab4e --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/parse-torture.sh @@ -0,0 +1,106 @@ +#!/bin/sh +# +# Check the console output from a torture run for goodness. +# The "file" is a pathname on the local system, and "title" is +# a text string for error-message purposes. +# +# The file must contain torture output, but can be interspersed +# with other dmesg text, as in console-log output. +# +# Usage: +#	sh parse-torture.sh file title +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2011 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +T=/tmp/parse-torture.sh.$$ +file="$1" +title="$2" + +trap 'rm -f $T.seq' 0 + +. functions.sh + +# check for presence of torture output file. + +if test -f "$file" -a -r "$file" +then +	: +else +	echo $title unreadable torture output file: $file +	exit 1 +fi + +# check for abject failure + +if grep -q FAILURE $file || grep -q -e '-torture.*!!!' $file +then +	nerrs=`grep --binary-files=text '!!!' $file | tail -1 | awk '{for (i=NF-8;i<=NF;i++) sum+=$i; } END {print sum}'` +	print_bug $title FAILURE, $nerrs instances +	echo "   " $url +	exit +fi + +grep --binary-files=text 'torture:.*ver:' $file | grep --binary-files=text -v '(null)' | sed -e 's/^(initramfs)[^]]*] //' -e 's/^\[[^]]*] //' | +awk ' +BEGIN	{ +	ver = 0; +	badseq = 0; +	} + +	{ +	if (!badseq && ($5 + 0 != $5 || $5 <= ver)) { +		badseqno1 = ver; +		badseqno2 = $5; +		badseqnr = NR; +		badseq = 1; +	} +	ver = $5 +	} + +END	{ +	if (badseq) { +		if (badseqno1 == badseqno2 && badseqno2 == ver) +			print "GP HANG at " ver " torture stat " badseqnr; +		else +			print "BAD SEQ " badseqno1 ":" badseqno2 " last:" ver " version " badseqnr; +	} +	}' > $T.seq + +if grep -q SUCCESS $file +then +	if test -s $T.seq +	then +		print_warning $title $title `cat $T.seq` +		echo "   " $file +		exit 2 +	fi +else +	if grep -q "_HOTPLUG:" $file +	then +		print_warning HOTPLUG FAILURES $title `cat $T.seq` +		echo "   " $file +		exit 3 +	fi +	echo $title no success message, `grep --binary-files=text 'ver:' $file | wc -l` successful version messages +	if test -s $T.seq +	then +		print_warning $title `cat $T.seq` +	fi +	exit 2 +fi diff --git a/tools/testing/selftests/rcutorture/configs/lock/BUSTED b/tools/testing/selftests/rcutorture/configs/lock/BUSTED new file mode 100644 index 00000000000..1d1da1477fc --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/BUSTED @@ -0,0 +1,6 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y diff --git a/tools/testing/selftests/rcutorture/configs/lock/BUSTED.boot b/tools/testing/selftests/rcutorture/configs/lock/BUSTED.boot new file mode 100644 index 00000000000..6386c15e977 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/BUSTED.boot @@ -0,0 +1 @@ +locktorture.torture_type=lock_busted diff --git a/tools/testing/selftests/rcutorture/configs/lock/CFLIST b/tools/testing/selftests/rcutorture/configs/lock/CFLIST new file mode 100644 index 00000000000..a061b22d189 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/CFLIST @@ -0,0 +1 @@ +LOCK01 diff --git a/tools/testing/selftests/rcutorture/configs/lock/CFcommon b/tools/testing/selftests/rcutorture/configs/lock/CFcommon new file mode 100644 index 00000000000..e372dc26925 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/CFcommon @@ -0,0 +1,2 @@ +CONFIG_LOCK_TORTURE_TEST=y +CONFIG_PRINTK_TIME=y diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK01 b/tools/testing/selftests/rcutorture/configs/lock/LOCK01 new file mode 100644 index 00000000000..a9625e3d6cd --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK01 @@ -0,0 +1,6 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=8 +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y diff --git a/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh new file mode 100644 index 00000000000..9746ea1cd6c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# +# Kernel-version-dependent shell functions for the rest of the scripts. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2014 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +# locktorture_param_onoff bootparam-string config-file +# +# Adds onoff locktorture module parameters to kernels having it. +locktorture_param_onoff () { +	if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2" +	then +		echo CPU-hotplug kernel, adding locktorture onoff. 1>&2 +		echo locktorture.onoff_interval=3 locktorture.onoff_holdoff=30 +	fi +} + +# per_version_boot_params bootparam-string config-file seconds +# +# Adds per-version torture-module parameters to kernels supporting them. +per_version_boot_params () { +	echo $1 `locktorture_param_onoff "$1" "$2"` \ +		locktorture.stat_interval=15 \ +		locktorture.shutdown_secs=$3 \ +		locktorture.locktorture_runnable=1 \ +		locktorture.verbose=1 +} diff --git a/tools/testing/selftests/rcutorture/configs/rcu/BUSTED b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED new file mode 100644 index 00000000000..48d8a245c7f --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED @@ -0,0 +1,7 @@ +CONFIG_RCU_TRACE=n +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y diff --git a/tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot new file mode 100644 index 00000000000..6804f9dcfc1 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot @@ -0,0 +1 @@ +rcutorture.torture_type=rcu_busted diff --git a/tools/testing/selftests/rcutorture/configs/rcu/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST new file mode 100644 index 00000000000..cd3d29cb0a4 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST @@ -0,0 +1,13 @@ +TREE01 +TREE02 +TREE03 +TREE04 +TREE05 +TREE06 +TREE07 +TREE08 +TREE09 +SRCU-N +SRCU-P +TINY01 +TINY02 diff --git a/tools/testing/selftests/rcutorture/configs/rcu/CFcommon b/tools/testing/selftests/rcutorture/configs/rcu/CFcommon new file mode 100644 index 00000000000..d2d2a86139d --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/CFcommon @@ -0,0 +1,2 @@ +CONFIG_RCU_TORTURE_TEST=y +CONFIG_PRINTK_TIME=y diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N new file mode 100644 index 00000000000..9fbb41b9b31 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N @@ -0,0 +1,7 @@ +CONFIG_RCU_TRACE=n +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N.boot b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N.boot new file mode 100644 index 00000000000..238bfe3bd0c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N.boot @@ -0,0 +1 @@ +rcutorture.torture_type=srcu diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P new file mode 100644 index 00000000000..4b6f272dba2 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P @@ -0,0 +1,7 @@ +CONFIG_RCU_TRACE=n +CONFIG_SMP=y +CONFIG_NR_CPUS=8 +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P.boot b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P.boot new file mode 100644 index 00000000000..238bfe3bd0c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P.boot @@ -0,0 +1 @@ +rcutorture.torture_type=srcu diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TINY01 b/tools/testing/selftests/rcutorture/configs/rcu/TINY01 new file mode 100644 index 00000000000..0a63e073a00 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TINY01 @@ -0,0 +1,12 @@ +CONFIG_SMP=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TINY_RCU=y +CONFIG_HZ_PERIODIC=n +CONFIG_NO_HZ_IDLE=y +CONFIG_NO_HZ_FULL=n +CONFIG_RCU_TRACE=n +CONFIG_DEBUG_LOCK_ALLOC=n +CONFIG_DEBUG_OBJECTS_RCU_HEAD=n +CONFIG_PREEMPT_COUNT=n diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TINY02 b/tools/testing/selftests/rcutorture/configs/rcu/TINY02 new file mode 100644 index 00000000000..f4feaee4077 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TINY02 @@ -0,0 +1,12 @@ +CONFIG_SMP=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TINY_RCU=y +CONFIG_HZ_PERIODIC=y +CONFIG_NO_HZ_IDLE=n +CONFIG_NO_HZ_FULL=n +CONFIG_RCU_TRACE=y +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=n +CONFIG_PREEMPT_COUNT=y diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE01 b/tools/testing/selftests/rcutorture/configs/rcu/TREE01 new file mode 100644 index 00000000000..9c827ec59a9 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01 @@ -0,0 +1,22 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=8 +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_HZ_PERIODIC=n +CONFIG_NO_HZ_IDLE=y +CONFIG_NO_HZ_FULL=n +CONFIG_RCU_FAST_NO_HZ=y +CONFIG_RCU_TRACE=y +CONFIG_HOTPLUG_CPU=y +CONFIG_RCU_FANOUT=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_ZERO=y +CONFIG_DEBUG_LOCK_ALLOC=n +CONFIG_PROVE_RCU_DELAY=n +CONFIG_RCU_CPU_STALL_INFO=n +CONFIG_RCU_CPU_STALL_VERBOSE=n +CONFIG_RCU_BOOST=n +CONFIG_DEBUG_OBJECTS_RCU_HEAD=n diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot new file mode 100644 index 00000000000..0fc8a342893 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot @@ -0,0 +1 @@ +rcutorture.torture_type=rcu_bh diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE02 b/tools/testing/selftests/rcutorture/configs/rcu/TREE02 new file mode 100644 index 00000000000..1a777b5f68b --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE02 @@ -0,0 +1,25 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=8 +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_HZ_PERIODIC=n +CONFIG_NO_HZ_IDLE=y +CONFIG_NO_HZ_FULL=n +CONFIG_RCU_FAST_NO_HZ=n +CONFIG_RCU_TRACE=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_RCU_FANOUT=3 +CONFIG_RCU_FANOUT_LEAF=3 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_RCU_NOCB_CPU=n +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=n +CONFIG_PROVE_RCU_DELAY=n +CONFIG_RCU_CPU_STALL_INFO=n +CONFIG_RCU_CPU_STALL_VERBOSE=y +CONFIG_RCU_BOOST=n +CONFIG_DEBUG_OBJECTS_RCU_HEAD=n diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE02-T b/tools/testing/selftests/rcutorture/configs/rcu/TREE02-T new file mode 100644 index 00000000000..61c8d9ce5bb --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE02-T @@ -0,0 +1,25 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=8 +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_HZ_PERIODIC=n +CONFIG_NO_HZ_IDLE=y +CONFIG_NO_HZ_FULL=n +CONFIG_RCU_FAST_NO_HZ=n +CONFIG_RCU_TRACE=y +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_RCU_FANOUT=3 +CONFIG_RCU_FANOUT_LEAF=3 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_RCU_NOCB_CPU=n +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=n +CONFIG_PROVE_RCU_DELAY=n +CONFIG_RCU_CPU_STALL_INFO=n +CONFIG_RCU_CPU_STALL_VERBOSE=y +CONFIG_RCU_BOOST=n +CONFIG_DEBUG_OBJECTS_RCU_HEAD=n diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE03 b/tools/testing/selftests/rcutorture/configs/rcu/TREE03 new file mode 100644 index 00000000000..c1f111c1561 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE03 @@ -0,0 +1,22 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=8 +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_HZ_PERIODIC=y +CONFIG_NO_HZ_IDLE=n +CONFIG_NO_HZ_FULL=n +CONFIG_RCU_TRACE=y +CONFIG_HOTPLUG_CPU=y +CONFIG_RCU_FANOUT=4 +CONFIG_RCU_FANOUT_LEAF=4 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_RCU_NOCB_CPU=n +CONFIG_DEBUG_LOCK_ALLOC=n +CONFIG_PROVE_RCU_DELAY=n +CONFIG_RCU_CPU_STALL_INFO=n +CONFIG_RCU_CPU_STALL_VERBOSE=n +CONFIG_RCU_BOOST=y +CONFIG_RCU_BOOST_PRIO=2 +CONFIG_DEBUG_OBJECTS_RCU_HEAD=n diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04 b/tools/testing/selftests/rcutorture/configs/rcu/TREE04 new file mode 100644 index 00000000000..7dbd27ce17a --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04 @@ -0,0 +1,24 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=8 +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_HZ_PERIODIC=n +CONFIG_NO_HZ_IDLE=n +CONFIG_NO_HZ_FULL=y +CONFIG_NO_HZ_FULL_ALL=y +CONFIG_RCU_FAST_NO_HZ=y +CONFIG_RCU_TRACE=y +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_RCU_FANOUT=2 +CONFIG_RCU_FANOUT_LEAF=2 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_RCU_NOCB_CPU=n +CONFIG_DEBUG_LOCK_ALLOC=n +CONFIG_PROVE_RCU_DELAY=n +CONFIG_RCU_CPU_STALL_INFO=y +CONFIG_RCU_CPU_STALL_VERBOSE=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=n diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot new file mode 100644 index 00000000000..0fc8a342893 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot @@ -0,0 +1 @@ +rcutorture.torture_type=rcu_bh diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE05 b/tools/testing/selftests/rcutorture/configs/rcu/TREE05 new file mode 100644 index 00000000000..d0f32e57474 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE05 @@ -0,0 +1,24 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=8 +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_HZ_PERIODIC=n +CONFIG_NO_HZ_IDLE=y +CONFIG_NO_HZ_FULL=n +CONFIG_RCU_FAST_NO_HZ=n +CONFIG_RCU_TRACE=n +CONFIG_HOTPLUG_CPU=y +CONFIG_RCU_FANOUT=6 +CONFIG_RCU_FANOUT_LEAF=6 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_NONE=y +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_PROVE_RCU_DELAY=y +CONFIG_RCU_CPU_STALL_INFO=n +CONFIG_RCU_CPU_STALL_VERBOSE=n +CONFIG_DEBUG_OBJECTS_RCU_HEAD=n diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot new file mode 100644 index 00000000000..3b42b8b033c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot @@ -0,0 +1 @@ +rcutorture.torture_type=sched diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE06 b/tools/testing/selftests/rcutorture/configs/rcu/TREE06 new file mode 100644 index 00000000000..2e477dfb9c5 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE06 @@ -0,0 +1,25 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=8 +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_HZ_PERIODIC=n +CONFIG_NO_HZ_IDLE=y +CONFIG_NO_HZ_FULL=n +CONFIG_RCU_FAST_NO_HZ=n +CONFIG_RCU_TRACE=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_RCU_FANOUT=6 +CONFIG_RCU_FANOUT_LEAF=6 +CONFIG_RCU_FANOUT_EXACT=y +CONFIG_RCU_NOCB_CPU=n +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_PROVE_RCU_DELAY=n +CONFIG_RCU_CPU_STALL_INFO=n +CONFIG_RCU_CPU_STALL_VERBOSE=n +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE07 b/tools/testing/selftests/rcutorture/configs/rcu/TREE07 new file mode 100644 index 00000000000..042f86ef362 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE07 @@ -0,0 +1,23 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=16 +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_HZ_PERIODIC=n +CONFIG_NO_HZ_IDLE=n +CONFIG_NO_HZ_FULL=y +CONFIG_NO_HZ_FULL_ALL=y +CONFIG_NO_HZ_FULL_SYSIDLE=y +CONFIG_RCU_FAST_NO_HZ=n +CONFIG_RCU_TRACE=y +CONFIG_HOTPLUG_CPU=y +CONFIG_RCU_FANOUT=2 +CONFIG_RCU_FANOUT_LEAF=2 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_RCU_NOCB_CPU=n +CONFIG_DEBUG_LOCK_ALLOC=n +CONFIG_PROVE_RCU_DELAY=n +CONFIG_RCU_CPU_STALL_INFO=y +CONFIG_RCU_CPU_STALL_VERBOSE=n +CONFIG_DEBUG_OBJECTS_RCU_HEAD=n diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE08 b/tools/testing/selftests/rcutorture/configs/rcu/TREE08 new file mode 100644 index 00000000000..3438cee1e3c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08 @@ -0,0 +1,25 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=16 +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_HZ_PERIODIC=n +CONFIG_NO_HZ_IDLE=y +CONFIG_NO_HZ_FULL=n +CONFIG_RCU_FAST_NO_HZ=n +CONFIG_RCU_TRACE=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_RCU_FANOUT=3 +CONFIG_RCU_FANOUT_EXACT=y +CONFIG_RCU_FANOUT_LEAF=2 +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_ALL=y +CONFIG_DEBUG_LOCK_ALLOC=n +CONFIG_PROVE_RCU_DELAY=n +CONFIG_RCU_CPU_STALL_INFO=n +CONFIG_RCU_CPU_STALL_VERBOSE=n +CONFIG_RCU_BOOST=n +CONFIG_DEBUG_OBJECTS_RCU_HEAD=n diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T b/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T new file mode 100644 index 00000000000..bf4523d3e44 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T @@ -0,0 +1,25 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=16 +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_HZ_PERIODIC=n +CONFIG_NO_HZ_IDLE=y +CONFIG_NO_HZ_FULL=n +CONFIG_RCU_FAST_NO_HZ=n +CONFIG_RCU_TRACE=y +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_RCU_FANOUT=3 +CONFIG_RCU_FANOUT_EXACT=y +CONFIG_RCU_FANOUT_LEAF=2 +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_ALL=y +CONFIG_DEBUG_LOCK_ALLOC=n +CONFIG_PROVE_RCU_DELAY=n +CONFIG_RCU_CPU_STALL_INFO=n +CONFIG_RCU_CPU_STALL_VERBOSE=n +CONFIG_RCU_BOOST=n +CONFIG_DEBUG_OBJECTS_RCU_HEAD=n diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot new file mode 100644 index 00000000000..3b42b8b033c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot @@ -0,0 +1 @@ +rcutorture.torture_type=sched diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE09 b/tools/testing/selftests/rcutorture/configs/rcu/TREE09 new file mode 100644 index 00000000000..81e4f7c0bf0 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE09 @@ -0,0 +1,20 @@ +CONFIG_SMP=n +CONFIG_NR_CPUS=1 +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_HZ_PERIODIC=n +CONFIG_NO_HZ_IDLE=y +CONFIG_NO_HZ_FULL=n +CONFIG_RCU_TRACE=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_RCU_NOCB_CPU=n +CONFIG_DEBUG_LOCK_ALLOC=n +CONFIG_PROVE_RCU_DELAY=n +CONFIG_RCU_CPU_STALL_INFO=n +CONFIG_RCU_CPU_STALL_VERBOSE=n +CONFIG_RCU_BOOST=n +CONFIG_DEBUG_OBJECTS_RCU_HEAD=n diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST new file mode 100644 index 00000000000..18223947bbc --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST @@ -0,0 +1,14 @@ +P1-S-T-NH-SD-SMP-HP +P2-2-t-nh-sd-SMP-hp +P3-3-T-nh-SD-SMP-hp +P4-A-t-NH-sd-SMP-HP +P5-U-T-NH-sd-SMP-hp +N1-S-T-NH-SD-SMP-HP +N2-2-t-nh-sd-SMP-hp +N3-3-T-nh-SD-SMP-hp +N4-A-t-NH-sd-SMP-HP +N5-U-T-NH-sd-SMP-hp +PT1-nh +PT2-NH +NT1-nh +NT3-NH diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP new file mode 100644 index 00000000000..d3ef873eb6e --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP @@ -0,0 +1,18 @@ +CONFIG_RCU_TRACE=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=8 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp new file mode 100644 index 00000000000..02e418572b1 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp @@ -0,0 +1,20 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_RCU_FANOUT=4 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp new file mode 100644 index 00000000000..b3100f69c8c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp @@ -0,0 +1,22 @@ +CONFIG_RCU_TRACE=y +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_RCU_FANOUT=2 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP new file mode 100644 index 00000000000..c56b4453072 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP @@ -0,0 +1,18 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=6 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp new file mode 100644 index 00000000000..90d924fea9e --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp @@ -0,0 +1,22 @@ +CONFIG_RCU_TRACE=y +CONFIG_DEBUG_KERNEL=y +CONFIG_RCU_CPU_STALL_INFO=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=6 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=y +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh new file mode 100644 index 00000000000..023f312a931 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh @@ -0,0 +1,23 @@ +#CHECK#CONFIG_TINY_RCU=y +CONFIG_RCU_TRACE=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +# +CONFIG_SMP=n +# +CONFIG_HOTPLUG_CPU=n +# +CONFIG_NO_HZ=n +# +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH new file mode 100644 index 00000000000..6fd0235dae7 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH @@ -0,0 +1,20 @@ +#CHECK#CONFIG_TINY_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +# +CONFIG_SMP=n +# +CONFIG_HOTPLUG_CPU=n +# +CONFIG_NO_HZ=y +# +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP new file mode 100644 index 00000000000..f72402d7c13 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP @@ -0,0 +1,19 @@ +CONFIG_RCU_TRACE=y +CONFIG_RCU_CPU_STALL_INFO=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=8 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp new file mode 100644 index 00000000000..0f3b667d2a9 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp @@ -0,0 +1,20 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_RCU_FANOUT=4 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp new file mode 100644 index 00000000000..b035e141bf2 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp @@ -0,0 +1,20 @@ +CONFIG_RCU_TRACE=y +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_RCU_FANOUT=2 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP new file mode 100644 index 00000000000..3ccf6a9447f --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP @@ -0,0 +1,22 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=6 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_RT_MUTEXES=y +CONFIG_RCU_BOOST=y +CONFIG_RCU_BOOST_PRIO=2 +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp new file mode 100644 index 00000000000..ef624ce73d8 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp @@ -0,0 +1,28 @@ +CONFIG_RCU_TRACE=y +CONFIG_RCU_CPU_STALL_INFO=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=6 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=y +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_DEBUG_KERNEL=y +CONFIG_PROVE_RCU_DELAY=y +CONFIG_DEBUG_OBJECTS=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +CONFIG_RT_MUTEXES=y +CONFIG_RCU_BOOST=y +CONFIG_RCU_BOOST_PRIO=2 +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh new file mode 100644 index 00000000000..e3361c3894a --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh @@ -0,0 +1,23 @@ +CONFIG_TINY_PREEMPT_RCU=y +CONFIG_RCU_BOOST=y +CONFIG_RCU_BOOST_PRIO=2 +CONFIG_RCU_TRACE=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +# +CONFIG_SMP=n +# +CONFIG_HOTPLUG_CPU=n +# +CONFIG_NO_HZ=n +# +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH new file mode 100644 index 00000000000..64abfc3b4d9 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH @@ -0,0 +1,22 @@ +CONFIG_TINY_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +# +CONFIG_SMP=n +# +CONFIG_HOTPLUG_CPU=n +# +CONFIG_NO_HZ=y +# +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh new file mode 100644 index 00000000000..5ace37a8978 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# +# Kernel-version-dependent shell functions for the rest of the scripts. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2013 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +# per_version_boot_params bootparam-string config-file seconds +# +# Adds per-version torture-module parameters to kernels supporting them. +# Which old kernels do not. +per_version_boot_params () { +	echo	rcutorture.stat_interval=15 \ +		rcutorture.shutdown_secs=$3 \ +		rcutorture.rcutorture_runnable=1 \ +		rcutorture.test_no_idle_hz=1 \ +		rcutorture.verbose=1 +} diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST new file mode 100644 index 00000000000..da4cbc668f2 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST @@ -0,0 +1,17 @@ +sysidleY.2013.06.19a +sysidleN.2013.06.19a +P1-S-T-NH-SD-SMP-HP +P2-2-t-nh-sd-SMP-hp +P3-3-T-nh-SD-SMP-hp +P4-A-t-NH-sd-SMP-HP +P5-U-T-NH-sd-SMP-hp +P6---t-nh-SD-smp-hp +N1-S-T-NH-SD-SMP-HP +N2-2-t-nh-sd-SMP-hp +N3-3-T-nh-SD-SMP-hp +N4-A-t-NH-sd-SMP-HP +N5-U-T-NH-sd-SMP-hp +PT1-nh +PT2-NH +NT1-nh +NT3-NH diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP new file mode 100644 index 00000000000..d81e11d280a --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP @@ -0,0 +1,19 @@ +CONFIG_RCU_TRACE=y +CONFIG_RCU_FAST_NO_HZ=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=8 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp new file mode 100644 index 00000000000..02e418572b1 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp @@ -0,0 +1,20 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_RCU_FANOUT=4 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp new file mode 100644 index 00000000000..b3100f69c8c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp @@ -0,0 +1,22 @@ +CONFIG_RCU_TRACE=y +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_RCU_FANOUT=2 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP new file mode 100644 index 00000000000..c56b4453072 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP @@ -0,0 +1,18 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=6 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp new file mode 100644 index 00000000000..90d924fea9e --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp @@ -0,0 +1,22 @@ +CONFIG_RCU_TRACE=y +CONFIG_DEBUG_KERNEL=y +CONFIG_RCU_CPU_STALL_INFO=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=6 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=y +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp new file mode 100644 index 00000000000..0ccc36d7273 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp @@ -0,0 +1,19 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_NR_CPUS=1 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP new file mode 100644 index 00000000000..3f640cf8497 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP @@ -0,0 +1,26 @@ +CONFIG_RCU_TRACE=y +CONFIG_DEBUG_KERNEL=y +CONFIG_RCU_CPU_STALL_INFO=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=2 +CONFIG_NR_CPUS=16 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_NONE=y +CONFIG_RCU_NOCB_CPU_ZERO=n +CONFIG_RCU_NOCB_CPU_ALL=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP new file mode 100644 index 00000000000..285da2dd8ac --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP @@ -0,0 +1,22 @@ +CONFIG_RCU_TRACE=y +CONFIG_DEBUG_KERNEL=y +CONFIG_RCU_CPU_STALL_INFO=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=14 +CONFIG_NR_CPUS=16 +CONFIG_RCU_FANOUT_EXACT=y +CONFIG_HOTPLUG_CPU=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh new file mode 100644 index 00000000000..023f312a931 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh @@ -0,0 +1,23 @@ +#CHECK#CONFIG_TINY_RCU=y +CONFIG_RCU_TRACE=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +# +CONFIG_SMP=n +# +CONFIG_HOTPLUG_CPU=n +# +CONFIG_NO_HZ=n +# +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH new file mode 100644 index 00000000000..6fd0235dae7 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH @@ -0,0 +1,20 @@ +#CHECK#CONFIG_TINY_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +# +CONFIG_SMP=n +# +CONFIG_HOTPLUG_CPU=n +# +CONFIG_NO_HZ=y +# +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP new file mode 100644 index 00000000000..9647c44cf4b --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP @@ -0,0 +1,20 @@ +CONFIG_RCU_TRACE=y +CONFIG_RCU_CPU_STALL_INFO=y +CONFIG_NO_HZ=y +CONFIG_RCU_FAST_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=8 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp new file mode 100644 index 00000000000..0f3b667d2a9 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp @@ -0,0 +1,20 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_RCU_FANOUT=4 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp new file mode 100644 index 00000000000..b035e141bf2 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp @@ -0,0 +1,20 @@ +CONFIG_RCU_TRACE=y +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_RCU_FANOUT=2 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP new file mode 100644 index 00000000000..3ccf6a9447f --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP @@ -0,0 +1,22 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=6 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_RT_MUTEXES=y +CONFIG_RCU_BOOST=y +CONFIG_RCU_BOOST_PRIO=2 +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp new file mode 100644 index 00000000000..ef624ce73d8 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp @@ -0,0 +1,28 @@ +CONFIG_RCU_TRACE=y +CONFIG_RCU_CPU_STALL_INFO=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=6 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=y +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_DEBUG_KERNEL=y +CONFIG_PROVE_RCU_DELAY=y +CONFIG_DEBUG_OBJECTS=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +CONFIG_RT_MUTEXES=y +CONFIG_RCU_BOOST=y +CONFIG_RCU_BOOST_PRIO=2 +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp new file mode 100644 index 00000000000..f4c9175828b --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp @@ -0,0 +1,18 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=n +CONFIG_SMP=n +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP new file mode 100644 index 00000000000..77a8c5b7576 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP @@ -0,0 +1,30 @@ +CONFIG_RCU_TRACE=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=2 +CONFIG_NR_CPUS=16 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_NONE=n +CONFIG_RCU_NOCB_CPU_ZERO=n +CONFIG_RCU_NOCB_CPU_ALL=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_OBJECTS=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_SLUB=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all new file mode 100644 index 00000000000..0eecebc6e95 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all @@ -0,0 +1,30 @@ +CONFIG_RCU_TRACE=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=2 +CONFIG_NR_CPUS=16 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_NONE=y +CONFIG_RCU_NOCB_CPU_ZERO=n +CONFIG_RCU_NOCB_CPU_ALL=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_OBJECTS=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_SLUB=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none new file mode 100644 index 00000000000..0eecebc6e95 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none @@ -0,0 +1,30 @@ +CONFIG_RCU_TRACE=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=2 +CONFIG_NR_CPUS=16 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_NONE=y +CONFIG_RCU_NOCB_CPU_ZERO=n +CONFIG_RCU_NOCB_CPU_ALL=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_OBJECTS=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_SLUB=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp new file mode 100644 index 00000000000..588bc70420c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp @@ -0,0 +1,30 @@ +CONFIG_RCU_TRACE=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=2 +CONFIG_NR_CPUS=16 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_NONE=n +CONFIG_RCU_NOCB_CPU_ZERO=y +CONFIG_RCU_NOCB_CPU_ALL=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_OBJECTS=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_SLUB=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh new file mode 100644 index 00000000000..e3361c3894a --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh @@ -0,0 +1,23 @@ +CONFIG_TINY_PREEMPT_RCU=y +CONFIG_RCU_BOOST=y +CONFIG_RCU_BOOST_PRIO=2 +CONFIG_RCU_TRACE=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +# +CONFIG_SMP=n +# +CONFIG_HOTPLUG_CPU=n +# +CONFIG_NO_HZ=n +# +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH new file mode 100644 index 00000000000..64abfc3b4d9 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH @@ -0,0 +1,22 @@ +CONFIG_TINY_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +# +CONFIG_SMP=n +# +CONFIG_HOTPLUG_CPU=n +# +CONFIG_NO_HZ=y +# +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST new file mode 100644 index 00000000000..18223947bbc --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST @@ -0,0 +1,14 @@ +P1-S-T-NH-SD-SMP-HP +P2-2-t-nh-sd-SMP-hp +P3-3-T-nh-SD-SMP-hp +P4-A-t-NH-sd-SMP-HP +P5-U-T-NH-sd-SMP-hp +N1-S-T-NH-SD-SMP-HP +N2-2-t-nh-sd-SMP-hp +N3-3-T-nh-SD-SMP-hp +N4-A-t-NH-sd-SMP-HP +N5-U-T-NH-sd-SMP-hp +PT1-nh +PT2-NH +NT1-nh +NT3-NH diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP new file mode 100644 index 00000000000..d81e11d280a --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP @@ -0,0 +1,19 @@ +CONFIG_RCU_TRACE=y +CONFIG_RCU_FAST_NO_HZ=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=8 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp new file mode 100644 index 00000000000..02e418572b1 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp @@ -0,0 +1,20 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_RCU_FANOUT=4 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp new file mode 100644 index 00000000000..b3100f69c8c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp @@ -0,0 +1,22 @@ +CONFIG_RCU_TRACE=y +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_RCU_FANOUT=2 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP new file mode 100644 index 00000000000..c56b4453072 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP @@ -0,0 +1,18 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=6 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp new file mode 100644 index 00000000000..90d924fea9e --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp @@ -0,0 +1,22 @@ +CONFIG_RCU_TRACE=y +CONFIG_DEBUG_KERNEL=y +CONFIG_RCU_CPU_STALL_INFO=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=6 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=y +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh new file mode 100644 index 00000000000..023f312a931 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh @@ -0,0 +1,23 @@ +#CHECK#CONFIG_TINY_RCU=y +CONFIG_RCU_TRACE=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +# +CONFIG_SMP=n +# +CONFIG_HOTPLUG_CPU=n +# +CONFIG_NO_HZ=n +# +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH new file mode 100644 index 00000000000..6fd0235dae7 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH @@ -0,0 +1,20 @@ +#CHECK#CONFIG_TINY_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +# +CONFIG_SMP=n +# +CONFIG_HOTPLUG_CPU=n +# +CONFIG_NO_HZ=y +# +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP new file mode 100644 index 00000000000..9647c44cf4b --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP @@ -0,0 +1,20 @@ +CONFIG_RCU_TRACE=y +CONFIG_RCU_CPU_STALL_INFO=y +CONFIG_NO_HZ=y +CONFIG_RCU_FAST_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=8 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp new file mode 100644 index 00000000000..0f3b667d2a9 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp @@ -0,0 +1,20 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_RCU_FANOUT=4 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp new file mode 100644 index 00000000000..b035e141bf2 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp @@ -0,0 +1,20 @@ +CONFIG_RCU_TRACE=y +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_RCU_FANOUT=2 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP new file mode 100644 index 00000000000..3ccf6a9447f --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP @@ -0,0 +1,22 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=6 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_RT_MUTEXES=y +CONFIG_RCU_BOOST=y +CONFIG_RCU_BOOST_PRIO=2 +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp new file mode 100644 index 00000000000..ef624ce73d8 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp @@ -0,0 +1,28 @@ +CONFIG_RCU_TRACE=y +CONFIG_RCU_CPU_STALL_INFO=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=6 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=y +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_DEBUG_KERNEL=y +CONFIG_PROVE_RCU_DELAY=y +CONFIG_DEBUG_OBJECTS=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +CONFIG_RT_MUTEXES=y +CONFIG_RCU_BOOST=y +CONFIG_RCU_BOOST_PRIO=2 +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh new file mode 100644 index 00000000000..e3361c3894a --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh @@ -0,0 +1,23 @@ +CONFIG_TINY_PREEMPT_RCU=y +CONFIG_RCU_BOOST=y +CONFIG_RCU_BOOST_PRIO=2 +CONFIG_RCU_TRACE=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +# +CONFIG_SMP=n +# +CONFIG_HOTPLUG_CPU=n +# +CONFIG_NO_HZ=n +# +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH new file mode 100644 index 00000000000..64abfc3b4d9 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH @@ -0,0 +1,22 @@ +CONFIG_TINY_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +# +CONFIG_SMP=n +# +CONFIG_HOTPLUG_CPU=n +# +CONFIG_NO_HZ=y +# +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh new file mode 100644 index 00000000000..bae55692ce6 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# +# Kernel-version-dependent shell functions for the rest of the scripts. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2013 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +# rcutorture_param_onoff bootparam-string config-file +# +# Adds onoff rcutorture module parameters to kernels having it. +rcutorture_param_onoff () { +	if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2" +	then +		echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2 +		echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30 +	fi +} + +# per_version_boot_params bootparam-string config-file seconds +# +# Adds per-version torture-module parameters to kernels supporting them. +per_version_boot_params () { +	echo $1 `rcutorture_param_onoff "$1" "$2"` \ +		rcutorture.stat_interval=15 \ +		rcutorture.shutdown_secs=$3 \ +		rcutorture.rcutorture_runnable=1 \ +		rcutorture.test_no_idle_hz=1 \ +		rcutorture.verbose=1 +} diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST new file mode 100644 index 00000000000..18223947bbc --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST @@ -0,0 +1,14 @@ +P1-S-T-NH-SD-SMP-HP +P2-2-t-nh-sd-SMP-hp +P3-3-T-nh-SD-SMP-hp +P4-A-t-NH-sd-SMP-HP +P5-U-T-NH-sd-SMP-hp +N1-S-T-NH-SD-SMP-HP +N2-2-t-nh-sd-SMP-hp +N3-3-T-nh-SD-SMP-hp +N4-A-t-NH-sd-SMP-HP +N5-U-T-NH-sd-SMP-hp +PT1-nh +PT2-NH +NT1-nh +NT3-NH diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP new file mode 100644 index 00000000000..d81e11d280a --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP @@ -0,0 +1,19 @@ +CONFIG_RCU_TRACE=y +CONFIG_RCU_FAST_NO_HZ=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=8 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp new file mode 100644 index 00000000000..02e418572b1 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp @@ -0,0 +1,20 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_RCU_FANOUT=4 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp new file mode 100644 index 00000000000..b3100f69c8c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp @@ -0,0 +1,22 @@ +CONFIG_RCU_TRACE=y +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_RCU_FANOUT=2 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP new file mode 100644 index 00000000000..c56b4453072 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP @@ -0,0 +1,18 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=6 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp new file mode 100644 index 00000000000..90d924fea9e --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp @@ -0,0 +1,22 @@ +CONFIG_RCU_TRACE=y +CONFIG_DEBUG_KERNEL=y +CONFIG_RCU_CPU_STALL_INFO=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=6 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=y +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +#CHECK#CONFIG_TREE_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh new file mode 100644 index 00000000000..023f312a931 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh @@ -0,0 +1,23 @@ +#CHECK#CONFIG_TINY_RCU=y +CONFIG_RCU_TRACE=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +# +CONFIG_SMP=n +# +CONFIG_HOTPLUG_CPU=n +# +CONFIG_NO_HZ=n +# +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH new file mode 100644 index 00000000000..6fd0235dae7 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH @@ -0,0 +1,20 @@ +#CHECK#CONFIG_TINY_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +# +CONFIG_SMP=n +# +CONFIG_HOTPLUG_CPU=n +# +CONFIG_NO_HZ=y +# +CONFIG_PREEMPT_NONE=y +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=n +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP new file mode 100644 index 00000000000..9647c44cf4b --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP @@ -0,0 +1,20 @@ +CONFIG_RCU_TRACE=y +CONFIG_RCU_CPU_STALL_INFO=y +CONFIG_NO_HZ=y +CONFIG_RCU_FAST_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=8 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp new file mode 100644 index 00000000000..0f3b667d2a9 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp @@ -0,0 +1,20 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_RCU_FANOUT=4 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp new file mode 100644 index 00000000000..b035e141bf2 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp @@ -0,0 +1,20 @@ +CONFIG_RCU_TRACE=y +CONFIG_NO_HZ=n +CONFIG_SMP=y +CONFIG_RCU_FANOUT=2 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP new file mode 100644 index 00000000000..3ccf6a9447f --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP @@ -0,0 +1,22 @@ +CONFIG_RCU_TRACE=n +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=6 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=n +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_RT_MUTEXES=y +CONFIG_RCU_BOOST=y +CONFIG_RCU_BOOST_PRIO=2 +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp new file mode 100644 index 00000000000..ef624ce73d8 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp @@ -0,0 +1,28 @@ +CONFIG_RCU_TRACE=y +CONFIG_RCU_CPU_STALL_INFO=y +CONFIG_NO_HZ=y +CONFIG_SMP=y +CONFIG_RCU_FANOUT=6 +CONFIG_NR_CPUS=8 +CONFIG_RCU_FANOUT_EXACT=y +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_TREE_PREEMPT_RCU=y +CONFIG_DEBUG_KERNEL=y +CONFIG_PROVE_RCU_DELAY=y +CONFIG_DEBUG_OBJECTS=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +CONFIG_RT_MUTEXES=y +CONFIG_RCU_BOOST=y +CONFIG_RCU_BOOST_PRIO=2 +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh new file mode 100644 index 00000000000..e3361c3894a --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh @@ -0,0 +1,23 @@ +CONFIG_TINY_PREEMPT_RCU=y +CONFIG_RCU_BOOST=y +CONFIG_RCU_BOOST_PRIO=2 +CONFIG_RCU_TRACE=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +# +CONFIG_SMP=n +# +CONFIG_HOTPLUG_CPU=n +# +CONFIG_NO_HZ=n +# +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH new file mode 100644 index 00000000000..64abfc3b4d9 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH @@ -0,0 +1,22 @@ +CONFIG_TINY_PREEMPT_RCU=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_MODULE_UNLOAD=y +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +# +CONFIG_SMP=n +# +CONFIG_HOTPLUG_CPU=n +# +CONFIG_NO_HZ=y +# +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_PRINTK_TIME=y + diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh new file mode 100644 index 00000000000..8977d8d31b1 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# +# Kernel-version-dependent shell functions for the rest of the scripts. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2013 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +# rcutorture_param_n_barrier_cbs bootparam-string +# +# Adds n_barrier_cbs rcutorture module parameter to kernels having it. +rcutorture_param_n_barrier_cbs () { +	if echo $1 | grep -q "rcutorture\.n_barrier_cbs" +	then +		: +	else +		echo rcutorture.n_barrier_cbs=4 +	fi +} + +# rcutorture_param_onoff bootparam-string config-file +# +# Adds onoff rcutorture module parameters to kernels having it. +rcutorture_param_onoff () { +	if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2" +	then +		echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2 +		echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30 +	fi +} + +# per_version_boot_params bootparam-string config-file seconds +# +# Adds per-version torture-module parameters to kernels supporting them. +per_version_boot_params () { +	echo $1 `rcutorture_param_onoff "$1" "$2"` \ +		`rcutorture_param_n_barrier_cbs "$1"` \ +		rcutorture.stat_interval=15 \ +		rcutorture.shutdown_secs=$3 \ +		rcutorture.rcutorture_runnable=1 \ +		rcutorture.test_no_idle_hz=1 \ +		rcutorture.verbose=1 +} diff --git a/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh new file mode 100644 index 00000000000..8977d8d31b1 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# +# Kernel-version-dependent shell functions for the rest of the scripts. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2013 +# +# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + +# rcutorture_param_n_barrier_cbs bootparam-string +# +# Adds n_barrier_cbs rcutorture module parameter to kernels having it. +rcutorture_param_n_barrier_cbs () { +	if echo $1 | grep -q "rcutorture\.n_barrier_cbs" +	then +		: +	else +		echo rcutorture.n_barrier_cbs=4 +	fi +} + +# rcutorture_param_onoff bootparam-string config-file +# +# Adds onoff rcutorture module parameters to kernels having it. +rcutorture_param_onoff () { +	if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2" +	then +		echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2 +		echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30 +	fi +} + +# per_version_boot_params bootparam-string config-file seconds +# +# Adds per-version torture-module parameters to kernels supporting them. +per_version_boot_params () { +	echo $1 `rcutorture_param_onoff "$1" "$2"` \ +		`rcutorture_param_n_barrier_cbs "$1"` \ +		rcutorture.stat_interval=15 \ +		rcutorture.shutdown_secs=$3 \ +		rcutorture.rcutorture_runnable=1 \ +		rcutorture.test_no_idle_hz=1 \ +		rcutorture.verbose=1 +} diff --git a/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt b/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt new file mode 100644 index 00000000000..28db67b54e5 --- /dev/null +++ b/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt @@ -0,0 +1,40 @@ +This document gives a brief rationale for the TINY_RCU test cases. + + +Kconfig Parameters: + +CONFIG_DEBUG_LOCK_ALLOC -- Do all three and none of the three. +CONFIG_PREEMPT_COUNT +CONFIG_RCU_TRACE + +The theory here is that randconfig testing will hit the other six possible +combinations of these parameters. + + +Kconfig Parameters Ignored: + +CONFIG_DEBUG_OBJECTS_RCU_HEAD +CONFIG_PROVE_RCU + +	In common code tested by TREE_RCU test cases. + +CONFIG_NO_HZ_FULL_SYSIDLE +CONFIG_RCU_NOCB_CPU +CONFIG_RCU_USER_QS + +	Meaningless for TINY_RCU. + +CONFIG_RCU_STALL_COMMON +CONFIG_RCU_TORTURE_TEST + +	Redundant with CONFIG_RCU_TRACE. + +CONFIG_HOTPLUG_CPU +CONFIG_PREEMPT +CONFIG_PREEMPT_RCU +CONFIG_SMP +CONFIG_TINY_RCU +CONFIG_TREE_PREEMPT_RCU +CONFIG_TREE_RCU + +	All forced by CONFIG_TINY_RCU. diff --git a/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt new file mode 100644 index 00000000000..adbb76cffb4 --- /dev/null +++ b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt @@ -0,0 +1,95 @@ +This document gives a brief rationale for the TREE_RCU-related test +cases, a group that includes TREE_PREEMPT_RCU. + + +Kconfig Parameters: + +CONFIG_DEBUG_LOCK_ALLOC -- Do three, covering CONFIG_PROVE_LOCKING & not. +CONFIG_DEBUG_OBJECTS_RCU_HEAD -- Do one. +CONFIG_HOTPLUG_CPU -- Do half.  (Every second.) +CONFIG_HZ_PERIODIC -- Do one. +CONFIG_NO_HZ_IDLE -- Do those not otherwise specified. (Groups of two.) +CONFIG_NO_HZ_FULL -- Do two, one with CONFIG_NO_HZ_FULL_SYSIDLE. +CONFIG_NO_HZ_FULL_SYSIDLE -- Do one. +CONFIG_PREEMPT -- Do half.  (First three and #8.) +CONFIG_PROVE_LOCKING -- Do all but two, covering CONFIG_PROVE_RCU and not. +CONFIG_PROVE_RCU -- Do all but one under CONFIG_PROVE_LOCKING. +CONFIG_PROVE_RCU_DELAY -- Do one. +CONFIG_RCU_BOOST -- one of TREE_PREEMPT_RCU. +CONFIG_RCU_BOOST_PRIO -- set to 2 for _BOOST testing. +CONFIG_RCU_CPU_STALL_INFO -- do one with and without _VERBOSE. +CONFIG_RCU_CPU_STALL_VERBOSE -- do one with and without _INFO. +CONFIG_RCU_FANOUT -- Cover hierarchy as currently, but overlap with others. +CONFIG_RCU_FANOUT_EXACT -- Do one. +CONFIG_RCU_FANOUT_LEAF -- Do one non-default. +CONFIG_RCU_FAST_NO_HZ -- Do one, but not with CONFIG_RCU_NOCB_CPU_ALL. +CONFIG_RCU_NOCB_CPU -- Do three, see below. +CONFIG_RCU_NOCB_CPU_ALL -- Do one. +CONFIG_RCU_NOCB_CPU_NONE -- Do one. +CONFIG_RCU_NOCB_CPU_ZERO -- Do one. +CONFIG_RCU_TRACE -- Do half. +CONFIG_SMP -- Need one !SMP for TREE_PREEMPT_RCU. +RCU-bh: Do one with PREEMPT and one with !PREEMPT. +RCU-sched: Do one with PREEMPT but not BOOST. + + +Hierarchy: + +TREE01.	CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=8, CONFIG_RCU_FANOUT_EXACT=n. +TREE02.	CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=3, CONFIG_RCU_FANOUT_EXACT=n, +	CONFIG_RCU_FANOUT_LEAF=3. +TREE03.	CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=4, CONFIG_RCU_FANOUT_EXACT=n, +	CONFIG_RCU_FANOUT_LEAF=4. +TREE04.	CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=2, CONFIG_RCU_FANOUT_EXACT=n, +	CONFIG_RCU_FANOUT_LEAF=2. +TREE05.	CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=6, CONFIG_RCU_FANOUT_EXACT=n +	CONFIG_RCU_FANOUT_LEAF=6. +TREE06.	CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=6, CONFIG_RCU_FANOUT_EXACT=y +	CONFIG_RCU_FANOUT_LEAF=6. +TREE07.	CONFIG_NR_CPUS=16, CONFIG_RCU_FANOUT=2, CONFIG_RCU_FANOUT_EXACT=n, +	CONFIG_RCU_FANOUT_LEAF=2. +TREE08.	CONFIG_NR_CPUS=16, CONFIG_RCU_FANOUT=3, CONFIG_RCU_FANOUT_EXACT=y, +	CONFIG_RCU_FANOUT_LEAF=2. +TREE09.	CONFIG_NR_CPUS=1. + + +Kconfig Parameters Ignored: + +CONFIG_64BIT + +	Used only to check CONFIG_RCU_FANOUT value, inspection suffices. + +CONFIG_NO_HZ_FULL_SYSIDLE_SMALL + +	Defer until Frederic uses this. + +CONFIG_PREEMPT_COUNT +CONFIG_PREEMPT_RCU + +	Redundant with CONFIG_PREEMPT, ignore. + +CONFIG_RCU_BOOST_DELAY + +	Inspection suffices, ignore. + +CONFIG_RCU_CPU_STALL_TIMEOUT + +	Inspection suffices, ignore. + +CONFIG_RCU_STALL_COMMON + +	Implied by TREE_RCU and TREE_PREEMPT_RCU. + +CONFIG_RCU_TORTURE_TEST +CONFIG_RCU_TORTURE_TEST_RUNNABLE + +	Always used in KVM testing. + +CONFIG_RCU_USER_QS + +	Redundant with CONFIG_NO_HZ_FULL. + +CONFIG_TREE_PREEMPT_RCU +CONFIG_TREE_RCU + +	These are controlled by CONFIG_PREEMPT. diff --git a/tools/testing/selftests/rcutorture/doc/initrd.txt b/tools/testing/selftests/rcutorture/doc/initrd.txt new file mode 100644 index 00000000000..49d134c25c0 --- /dev/null +++ b/tools/testing/selftests/rcutorture/doc/initrd.txt @@ -0,0 +1,90 @@ +This document describes one way to create the initrd directory hierarchy +in order to allow an initrd to be built into your kernel.  The trick +here is to steal the initrd file used on your Linux laptop, Ubuntu in +this case.  There are probably much better ways of doing this. + +That said, here are the commands: + +------------------------------------------------------------------------ +zcat /initrd.img > /tmp/initrd.img.zcat +mkdir initrd +cd initrd +cpio -id < /tmp/initrd.img.zcat +------------------------------------------------------------------------ + +Interestingly enough, if you are running rcutorture, you don't really +need userspace in many cases.  Running without userspace has the +advantage of allowing you to test your kernel independently of the +distro in place, the root-filesystem layout, and so on.  To make this +happen, put the following script in the initrd's tree's "/init" file, +with 0755 mode. + +------------------------------------------------------------------------ +#!/bin/sh + +[ -d /dev ] || mkdir -m 0755 /dev +[ -d /root ] || mkdir -m 0700 /root +[ -d /sys ] || mkdir /sys +[ -d /proc ] || mkdir /proc +[ -d /tmp ] || mkdir /tmp +mkdir -p /var/lock +mount -t sysfs -o nodev,noexec,nosuid sysfs /sys +mount -t proc -o nodev,noexec,nosuid proc /proc +# Some things don't work properly without /etc/mtab. +ln -sf /proc/mounts /etc/mtab + +# Note that this only becomes /dev on the real filesystem if udev's scripts +# are used; which they will be, but it's worth pointing out +if ! mount -t devtmpfs -o mode=0755 udev /dev; then +	echo "W: devtmpfs not available, falling back to tmpfs for /dev" +	mount -t tmpfs -o mode=0755 udev /dev +	[ -e /dev/console ] || mknod --mode=600 /dev/console c 5 1 +	[ -e /dev/kmsg ] || mknod --mode=644 /dev/kmsg c 1 11 +	[ -e /dev/null ] || mknod --mode=666 /dev/null c 1 3 +fi + +mkdir /dev/pts +mount -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /dev/pts || true +mount -t tmpfs -o "nosuid,size=20%,mode=0755" tmpfs /run +mkdir /run/initramfs +# compatibility symlink for the pre-oneiric locations +ln -s /run/initramfs /dev/.initramfs + +# Export relevant variables +export ROOT= +export ROOTDELAY= +export ROOTFLAGS= +export ROOTFSTYPE= +export IP= +export BOOT= +export BOOTIF= +export UBIMTD= +export break= +export init=/sbin/init +export quiet=n +export readonly=y +export rootmnt=/root +export debug= +export panic= +export blacklist= +export resume= +export resume_offset= +export recovery= + +for i in /sys/devices/system/cpu/cpu*/online +do +	case $i in +	'/sys/devices/system/cpu/cpu0/online') +		;; +	'/sys/devices/system/cpu/cpu*/online') +		;; +	*) +		echo 1 > $i +		;; +	esac +done + +while : +do +	sleep 10 +done diff --git a/tools/testing/selftests/rcutorture/doc/rcu-test-image.txt b/tools/testing/selftests/rcutorture/doc/rcu-test-image.txt new file mode 100644 index 00000000000..66efb59a1bd --- /dev/null +++ b/tools/testing/selftests/rcutorture/doc/rcu-test-image.txt @@ -0,0 +1,42 @@ +This document describes one way to created the rcu-test-image file +that contains the filesystem used by the guest-OS kernel.  There are +probably much better ways of doing this, and this filesystem could no +doubt be smaller.  It is probably also possible to simply download +an appropriate image from any number of places. + +That said, here are the commands: + +------------------------------------------------------------------------ +dd if=/dev/zero of=rcu-test-image bs=400M count=1 +mkfs.ext3 ./rcu-test-image +sudo mount -o loop ./rcu-test-image /mnt + +# Replace "precise" below with your favorite Ubuntu release. +# Empirical evidence says this image will work for 64-bit, but... +# Note that debootstrap does take a few minutes to run.  Or longer. +sudo debootstrap --verbose --arch i386 precise /mnt http://archive.ubuntu.com/ubuntu +cat << '___EOF___' | sudo dd of=/mnt/etc/fstab +# UNCONFIGURED FSTAB FOR BASE SYSTEM +# +/dev/vda        /               ext3    defaults        1 1 +dev             /dev            tmpfs   rw              0 0 +tmpfs           /dev/shm        tmpfs   defaults        0 0 +devpts          /dev/pts        devpts  gid=5,mode=620  0 0 +sysfs           /sys            sysfs   defaults        0 0 +proc            /proc           proc    defaults        0 0 +___EOF___ +sudo umount /mnt +------------------------------------------------------------------------ + + +References: + +	http://sripathikodi.blogspot.com/2010/02/creating-kvm-bootable-fedora-system.html +	https://help.ubuntu.com/community/KVM/CreateGuests +	https://help.ubuntu.com/community/JeOSVMBuilder +	http://wiki.libvirt.org/page/UbuntuKVMWalkthrough +	http://www.moe.co.uk/2011/01/07/pci_add_option_rom-failed-to-find-romfile-pxe-rtl8139-bin/ -- "apt-get install kvm-pxe" +	http://www.landley.net/writing/rootfs-howto.html +	http://en.wikipedia.org/wiki/Initrd +	http://en.wikipedia.org/wiki/Cpio +	http://wiki.libvirt.org/page/UbuntuKVMWalkthrough diff --git a/tools/testing/selftests/sysctl/Makefile b/tools/testing/selftests/sysctl/Makefile new file mode 100644 index 00000000000..0a92adaf086 --- /dev/null +++ b/tools/testing/selftests/sysctl/Makefile @@ -0,0 +1,19 @@ +# Makefile for sysctl selftests. +# Expects kernel.sysctl_writes_strict=1. + +# No binaries, but make sure arg-less "make" doesn't trigger "run_tests". +all: + +# Allow specific tests to be selected. +test_num: +	@/bin/sh ./run_numerictests + +test_string: +	@/bin/sh ./run_stringtests + +run_tests: all test_num test_string + +# Nothing to clean up. +clean: + +.PHONY: all run_tests clean test_num test_string diff --git a/tools/testing/selftests/sysctl/common_tests b/tools/testing/selftests/sysctl/common_tests new file mode 100644 index 00000000000..17d534b1b7b --- /dev/null +++ b/tools/testing/selftests/sysctl/common_tests @@ -0,0 +1,109 @@ +#!/bin/sh + +TEST_FILE=$(mktemp) + +echo "== Testing sysctl behavior against ${TARGET} ==" + +set_orig() +{ +	echo "${ORIG}" > "${TARGET}" +} + +set_test() +{ +	echo "${TEST_STR}" > "${TARGET}" +} + +verify() +{ +	local seen +	seen=$(cat "$1") +	if [ "${seen}" != "${TEST_STR}" ]; then +		return 1 +	fi +	return 0 +} + +trap 'set_orig; rm -f "${TEST_FILE}"' EXIT + +rc=0 + +echo -n "Writing test file ... " +echo "${TEST_STR}" > "${TEST_FILE}" +if ! verify "${TEST_FILE}"; then +	echo "FAIL" >&2 +	exit 1 +else +	echo "ok" +fi + +echo -n "Checking sysctl is not set to test value ... " +if verify "${TARGET}"; then +	echo "FAIL" >&2 +	exit 1 +else +	echo "ok" +fi + +echo -n "Writing sysctl from shell ... " +set_test +if ! verify "${TARGET}"; then +	echo "FAIL" >&2 +	exit 1 +else +	echo "ok" +fi + +echo -n "Resetting sysctl to original value ... " +set_orig +if verify "${TARGET}"; then +	echo "FAIL" >&2 +	exit 1 +else +	echo "ok" +fi + +# Now that we've validated the sanity of "set_test" and "set_orig", +# we can use those functions to set starting states before running +# specific behavioral tests. + +echo -n "Writing entire sysctl in single write ... " +set_orig +dd if="${TEST_FILE}" of="${TARGET}" bs=4096 2>/dev/null +if ! verify "${TARGET}"; then +	echo "FAIL" >&2 +	rc=1 +else +	echo "ok" +fi + +echo -n "Writing middle of sysctl after synchronized seek ... " +set_test +dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 skip=1 2>/dev/null +if ! verify "${TARGET}"; then +	echo "FAIL" >&2 +	rc=1 +else +	echo "ok" +fi + +echo -n "Writing beyond end of sysctl ... " +set_orig +dd if="${TEST_FILE}" of="${TARGET}" bs=20 seek=2 2>/dev/null +if verify "${TARGET}"; then +        echo "FAIL" >&2 +        rc=1 +else +        echo "ok" +fi + +echo -n "Writing sysctl with multiple long writes ... " +set_orig +(perl -e 'print "A" x 50;'; echo "${TEST_STR}") | \ +	dd of="${TARGET}" bs=50 2>/dev/null +if verify "${TARGET}"; then +	echo "FAIL" >&2 +	rc=1 +else +	echo "ok" +fi diff --git a/tools/testing/selftests/sysctl/run_numerictests b/tools/testing/selftests/sysctl/run_numerictests new file mode 100644 index 00000000000..8510f93f2d1 --- /dev/null +++ b/tools/testing/selftests/sysctl/run_numerictests @@ -0,0 +1,10 @@ +#!/bin/sh + +SYSCTL="/proc/sys" +TARGET="${SYSCTL}/vm/swappiness" +ORIG=$(cat "${TARGET}") +TEST_STR=$(( $ORIG + 1 )) + +. ./common_tests + +exit $rc diff --git a/tools/testing/selftests/sysctl/run_stringtests b/tools/testing/selftests/sysctl/run_stringtests new file mode 100644 index 00000000000..90a9293d520 --- /dev/null +++ b/tools/testing/selftests/sysctl/run_stringtests @@ -0,0 +1,77 @@ +#!/bin/sh + +SYSCTL="/proc/sys" +TARGET="${SYSCTL}/kernel/domainname" +ORIG=$(cat "${TARGET}") +TEST_STR="Testing sysctl" + +. ./common_tests + +# Only string sysctls support seeking/appending. +MAXLEN=65 + +echo -n "Writing entire sysctl in short writes ... " +set_orig +dd if="${TEST_FILE}" of="${TARGET}" bs=1 2>/dev/null +if ! verify "${TARGET}"; then +	echo "FAIL" >&2 +	rc=1 +else +	echo "ok" +fi + +echo -n "Writing middle of sysctl after unsynchronized seek ... " +set_test +dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 2>/dev/null +if verify "${TARGET}"; then +	echo "FAIL" >&2 +	rc=1 +else +	echo "ok" +fi + +echo -n "Checking sysctl maxlen is at least $MAXLEN ... " +set_orig +perl -e 'print "A" x ('"${MAXLEN}"'-2), "B";' | \ +	dd of="${TARGET}" bs="${MAXLEN}" 2>/dev/null +if ! grep -q B "${TARGET}"; then +	echo "FAIL" >&2 +	rc=1 +else +	echo "ok" +fi + +echo -n "Checking sysctl keeps original string on overflow append ... " +set_orig +perl -e 'print "A" x ('"${MAXLEN}"'-1), "B";' | \ +	dd of="${TARGET}" bs=$(( MAXLEN - 1 )) 2>/dev/null +if grep -q B "${TARGET}"; then +	echo "FAIL" >&2 +	rc=1 +else +	echo "ok" +fi + +echo -n "Checking sysctl stays NULL terminated on write ... " +set_orig +perl -e 'print "A" x ('"${MAXLEN}"'-1), "B";' | \ +	dd of="${TARGET}" bs="${MAXLEN}" 2>/dev/null +if grep -q B "${TARGET}"; then +	echo "FAIL" >&2 +	rc=1 +else +	echo "ok" +fi + +echo -n "Checking sysctl stays NULL terminated on overwrite ... " +set_orig +perl -e 'print "A" x ('"${MAXLEN}"'-1), "BB";' | \ +	dd of="${TARGET}" bs=$(( $MAXLEN + 1 )) 2>/dev/null +if grep -q B "${TARGET}"; then +	echo "FAIL" >&2 +	rc=1 +else +	echo "ok" +fi + +exit $rc diff --git a/tools/testing/selftests/timers/posix_timers.c b/tools/testing/selftests/timers/posix_timers.c index 4fa655d68a8..41bd85559d4 100644 --- a/tools/testing/selftests/timers/posix_timers.c +++ b/tools/testing/selftests/timers/posix_timers.c @@ -151,7 +151,7 @@ static int check_timer_create(int which)  	fflush(stdout);  	done = 0; -	timer_create(which, NULL, &id); +	err = timer_create(which, NULL, &id);  	if (err < 0) {  		perror("Can't create timer\n");  		return -1; diff --git a/tools/testing/selftests/user/Makefile b/tools/testing/selftests/user/Makefile new file mode 100644 index 00000000000..396255bd720 --- /dev/null +++ b/tools/testing/selftests/user/Makefile @@ -0,0 +1,13 @@ +# Makefile for user memory selftests + +# No binaries, but make sure arg-less "make" doesn't trigger "run_tests" +all: + +run_tests: all +	@if /sbin/modprobe test_user_copy ; then \ +		rmmod test_user_copy; \ +		echo "user_copy: ok"; \ +	else \ +		echo "user_copy: [FAIL]"; \ +		exit 1; \ +	fi  | 
