Message ID | 1421144560-15901-7-git-send-email-khandual@linux.vnet.ibm.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Michael Ellerman |
Headers | show |
On 01/13/2015 03:22 AM, Anshuman Khandual wrote: > This patch adds a test case for the system wide DSCR default > value, which when changed through it's sysfs interface must > be visible to all threads reading DSCR either through the > privilege state SPR or the problem state SPR. The DSCR value > change should be immediate as well. > > Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com> > --- > tools/testing/selftests/powerpc/Makefile | 2 +- > tools/testing/selftests/powerpc/dscr/Makefile | 17 +++ > tools/testing/selftests/powerpc/dscr/dscr.h | 120 ++++++++++++++++++++ > .../selftests/powerpc/dscr/dscr_default_test.c | 121 +++++++++++++++++++++ > 4 files changed, 259 insertions(+), 1 deletion(-) > create mode 100644 tools/testing/selftests/powerpc/dscr/Makefile > create mode 100644 tools/testing/selftests/powerpc/dscr/dscr.h > create mode 100644 tools/testing/selftests/powerpc/dscr/dscr_default_test.c > > diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile > index f6ff90a..1318883 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 copyloops mm tm primitives > +TARGETS = pmu copyloops mm tm primitives dscr > > endif > > diff --git a/tools/testing/selftests/powerpc/dscr/Makefile b/tools/testing/selftests/powerpc/dscr/Makefile > new file mode 100644 > index 0000000..0aa90ab > --- /dev/null > +++ b/tools/testing/selftests/powerpc/dscr/Makefile > @@ -0,0 +1,17 @@ > +PROGS := dscr_default_test > + > +CFLAGS := $(CFLAGS) -lpthread > + > +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/dscr/dscr.h b/tools/testing/selftests/powerpc/dscr/dscr.h > new file mode 100644 > index 0000000..2e6535b > --- /dev/null > +++ b/tools/testing/selftests/powerpc/dscr/dscr.h > @@ -0,0 +1,120 @@ > +/* > + * POWER Data Stream Control Register (DSCR) > + * > + * This header file contains helper functions and macros > + * required for all the DSCR related test cases. > + * > + * Copyright (C) 2012 Anton Blanchard <anton@au.ibm.com>, IBM > + * Copyright (C) 2015 Anshuman Khandual <khandual@linux.vnet.ibm.com>, IBM > + * > + * 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. > + */ > +#ifndef _SELFTESTS_POWERPC_DSCR_DSCR_H > +#define _SELFTESTS_POWERPC_DSCR_DSCR_H > + > +#include <unistd.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <fcntl.h> > +#include <dirent.h> > +#include <pthread.h> > +#include <sched.h> > +#include <sys/types.h> > +#include <sys/stat.h> > +#include <sys/wait.h> > + > +#include "utils.h" > + > +#define SPRN_DSCR 0x11 /* Privilege state SPR */ > +#define SPRN_DSCR_USR 0x03 /* Problem state SPR */ > +#define THREADS 100 /* Max threads */ > +#define COUNT 100 /* Max iterations */ > +#define DSCR_MAX 16 /* Max DSCR value */ > +#define LEN_MAX 100 /* Max name length */ > + > +#define DSCR_DEFAULT "/sys/devices/system/cpu/dscr_default" > +#define CPU_PATH "/sys/devices/system/cpu/" > + > +#define rmb() asm volatile("lwsync":::"memory") > +#define wmb() asm volatile("lwsync":::"memory") > + > +#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) > + > +/* Prilvilege state DSCR access */ > +inline unsigned long get_dscr(void) > +{ > + unsigned long ret; > + > + asm volatile("mfspr %0,%1" : "=r" (ret): "i" (SPRN_DSCR)); > + > + return ret; > +} > + > +inline void set_dscr(unsigned long val) > +{ > + asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR)); > +} > + > +/* Problem state DSCR access */ > +inline unsigned long get_dscr_usr(void) > +{ > + unsigned long ret; > + > + asm volatile("mfspr %0,%1" : "=r" (ret): "i" (SPRN_DSCR_USR)); > + > + return ret; > +} > + > +inline void set_dscr_usr(unsigned long val) > +{ > + asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR_USR)); > +} > + > +/* Default DSCR access */ > +unsigned long get_default_dscr(void) > +{ > + int fd = -1; > + char buf[16]; > + unsigned long val; > + > + if (fd == -1) { > + fd = open(DSCR_DEFAULT, O_RDONLY); > + if (fd == -1) { > + perror("open() failed\n"); > + exit(1); > + } > + } > + memset(buf, 0, sizeof(buf)); > + lseek(fd, 0, SEEK_SET); > + read(fd, buf, sizeof(buf)); > + sscanf(buf, "%lx", &val); > + close(fd); > + return val; > +} > + > +void set_default_dscr(unsigned long val) > +{ > + int fd = -1; > + char buf[16]; > + > + if (fd == -1) { > + fd = open(DSCR_DEFAULT, O_RDWR); > + if (fd == -1) { > + perror("open() failed\n"); > + exit(1); > + } > + } > + sprintf(buf, "%lx\n", val); > + write(fd, buf, strlen(buf)); > + close(fd); > +} > + > +double uniform_deviate(int seed) > +{ > + return seed * (1.0 / (RAND_MAX + 1.0)); > +} > +#endif /* _SELFTESTS_POWERPC_DSCR_DSCR_H */ > diff --git a/tools/testing/selftests/powerpc/dscr/dscr_default_test.c b/tools/testing/selftests/powerpc/dscr/dscr_default_test.c > new file mode 100644 > index 0000000..fd8b7b9 > --- /dev/null > +++ b/tools/testing/selftests/powerpc/dscr/dscr_default_test.c > @@ -0,0 +1,121 @@ > +/* > + * POWER Data Stream Control Register (DSCR) default test > + * > + * This test modifies the system wide default DSCR through > + * it's sysfs interface and then verifies that all threads > + * see the correct changed DSCR value immediately. > + * > + * Copyright (C) 2012 Anton Blanchard <anton@au.ibm.com>, IBM > + * Copyright (C) 2015 Anshuman Khandual <khandual@linux.vnet.ibm.com>, IBM > + * > + * 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. > + */ > +#include "dscr.h" > + > +static unsigned long dscr; /* System DSCR default */ > +static unsigned long sequence; > +static unsigned long result[THREADS]; > + > +static void *do_test(void *in) > +{ > + unsigned long thread = (unsigned long)in; > + unsigned long i; > + > + for (i = 0; i < COUNT; i++) { > + unsigned long d, cur_dscr, cur_dscr_usr; > + unsigned long s1, s2; > + > + s1 = ACCESS_ONCE(sequence); > + if (s1 & 1) > + continue; > + rmb(); > + > + d = dscr; > + cur_dscr = get_dscr(); > + cur_dscr_usr = get_dscr_usr(); > + > + rmb(); > + s2 = sequence; > + > + if (s1 != s2) > + continue; > + > + if (cur_dscr != d) { > + fprintf(stderr, "thread %ld kernel DSCR should be %ld " > + "but is %ld\n", thread, d, cur_dscr); > + result[thread] = 1; > + pthread_exit(&result[thread]); > + } > + > + if (cur_dscr_usr != d) { > + fprintf(stderr, "thread %ld user DSCR should be %ld " > + "but is %ld\n", thread, d, cur_dscr_usr); > + result[thread] = 1; > + pthread_exit(&result[thread]); > + } > + } > + result[thread] = 0; > + pthread_exit(&result[thread]); > +} > + > +int test_body(void) > +{ > + pthread_t threads[THREADS]; > + unsigned long i, *status[THREADS]; > + > + /* Initial DSCR default */ > + dscr = 1; > + set_default_dscr(dscr); > + > + /* Spawn all testing threads */ > + for (i = 0; i < THREADS; i++) { > + if (pthread_create(&threads[i], NULL, do_test, (void *)i)) { > + perror("pthread_create() failed\n"); > + exit(1); > + } > + } > + > + srand(getpid()); > + > + /* Keep changing the DSCR default */ > + for (i = 0; i < COUNT; i++) { > + double ret = uniform_deviate(rand()); > + > + if (ret < 0.0001) { > + sequence++; > + wmb(); > + > + dscr++; > + if (dscr > DSCR_MAX) > + dscr = 0; > + > + set_default_dscr(dscr); > + > + wmb(); > + sequence++; > + } > + } > + > + /* Individual testing thread exit status */ > + for (i = 0; i < THREADS; i++) { > + if (pthread_join(threads[i], (void **)&(status[i]))) { > + perror("pthread_join() failed\n"); > + exit(1); > + } > + > + if (*status[i]) { > + printf("%ldth thread failed to join with %ld status\n", > + i, *status[i]); > + return 1; > + } > + } > + return 0; > +} > + > +int main(int argc, char *argv[]) > +{ > + return test_harness(test_body, "dscr_default_test"); > +} > Could you please add a .gitignore for powerpc targets as we discussed earlier. It can be separate patch. Also, I would like to see the test results reports using kselftest.h - it can be separate patch in the interest of getting tests in. Acked-by: Shuah Khan <shuahkh@osg.samsung.com> Please take this through powerpc maintainer git. thanks, -- Shuah
On Tue, 2015-01-13 at 08:22 -0700, Shuah Khan wrote: > On 01/13/2015 03:22 AM, Anshuman Khandual wrote: > > This patch adds a test case for the system wide DSCR default > > value, which when changed through it's sysfs interface must > > be visible to all threads reading DSCR either through the > > privilege state SPR or the problem state SPR. The DSCR value > > change should be immediate as well. > > > > Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com> > > --- > > tools/testing/selftests/powerpc/Makefile | 2 +- > > tools/testing/selftests/powerpc/dscr/Makefile | 17 +++ > > tools/testing/selftests/powerpc/dscr/dscr.h | 120 ++++++++++++++++++++ > > .../selftests/powerpc/dscr/dscr_default_test.c | 121 +++++++++++++++++++++ > > 4 files changed, 259 insertions(+), 1 deletion(-) > > create mode 100644 tools/testing/selftests/powerpc/dscr/Makefile > > create mode 100644 tools/testing/selftests/powerpc/dscr/dscr.h > > create mode 100644 tools/testing/selftests/powerpc/dscr/dscr_default_test.c > > Could you please add a .gitignore for powerpc targets as we > discussed earlier. It can be separate patch. I can do that. > Also, I would like to see the test results reports using > kselftest.h - it can be separate patch in the interest of > getting tests in. Sorry but kselftest.h doesn't do anything useful for us. We have existing test reporting that uses the subunit protocol. I'm happy to convert that to TAP, or some other well defined output format, but not to something ad-hoc like kselftest.h currently provides. cheers
On Wed, Jan 14, 2015 at 10:44:31AM +1100, Michael Ellerman wrote: > > Also, I would like to see the test results reports using > > kselftest.h - it can be separate patch in the interest of > > getting tests in. > > Sorry but kselftest.h doesn't do anything useful for us. > > We have existing test reporting that uses the subunit protocol. > > I'm happy to convert that to TAP, or some other well defined output format, but > not to something ad-hoc like kselftest.h currently provides. Something TAP-alike would also help reduce some of the spew from tests that are going to fail. eg, running execveat tests on a kernel that doesn't implement that syscall currently spews around 20 lines of [FAIL]. Adding something to the beginning of the test to set plan() accordingly if it detects -ENOSYS could make that output a little cleaner. That other projects (like jenkins, bug trackers etc) could consume the output of the test runs would be a nice bonus. I only recently started looking at kselftests and was surprised at the amount of variance we have in the way of printing 'Ok' '[OK]' 'ok...' etc. Dave
On Tue, 2015-01-20 at 16:40 -0500, Dave Jones wrote: > On Wed, Jan 14, 2015 at 10:44:31AM +1100, Michael Ellerman wrote: > > > > Also, I would like to see the test results reports using > > > kselftest.h - it can be separate patch in the interest of > > > getting tests in. > > > > Sorry but kselftest.h doesn't do anything useful for us. > > > > We have existing test reporting that uses the subunit protocol. > > > > I'm happy to convert that to TAP, or some other well defined output format, but > > not to something ad-hoc like kselftest.h currently provides. > > Something TAP-alike would also help reduce some of the spew from > tests that are going to fail. Possibly :) > eg, running execveat tests on a kernel that doesn't implement that > syscall currently spews around 20 lines of [FAIL]. Adding something > to the beginning of the test to set plan() accordingly if it detects > -ENOSYS could make that output a little cleaner. Yeah I'm a bit dubious about plan, it often ends up being a pain to calculate correctly and so it's either missing or wrong. The execveat test probably just needs an initial test that looks for ENOSYS and bails entirely. I'll write a patch. > That other projects (like jenkins, bug trackers etc) could consume > the output of the test runs would be a nice bonus. I only recently > started looking at kselftests and was surprised at the amount > of variance we have in the way of printing 'Ok' '[OK]' 'ok...' etc. Variance in output is annoying, but putting up too many barriers to entry for new tests is even less desirable IMHO. Our preference should always be for more tests in the tree, and we can clean up the output/reporting later. cheers
On Tue, 2015-13-01 at 10:22:34 UTC, Anshuman Khandual wrote: > This patch adds a test case for the system wide DSCR default > value, which when changed through it's sysfs interface must > be visible to all threads reading DSCR either through the > privilege state SPR or the problem state SPR. The DSCR value > change should be immediate as well. ... > + > +/* Default DSCR access */ > +unsigned long get_default_dscr(void) > +{ > + int fd = -1; > + char buf[16]; > + unsigned long val; > + > + if (fd == -1) { > + fd = open(DSCR_DEFAULT, O_RDONLY); > + if (fd == -1) { > + perror("open() failed\n"); > + exit(1); > + } > + } > + memset(buf, 0, sizeof(buf)); > + lseek(fd, 0, SEEK_SET); > + read(fd, buf, sizeof(buf)); This and the other tests are failing to build: In file included from dscr_default_test.c:16:0: dscr.h: In function ‘get_default_dscr’: dscr.h:93:6: error: ignoring return value of ‘read’, declared with attribute warn_unused_result [-Werror=unused-result] read(fd, buf, sizeof(buf)); ^ dscr.h: In function ‘set_default_dscr’: dscr.h:112:7: error: ignoring return value of ‘write’, declared with attribute warn_unused_result [-Werror=unused-result] write(fd, buf, strlen(buf)); ^ cc1: all warnings being treated as errors cheers
On 03/27/2015 05:31 PM, Michael Ellerman wrote: > On Tue, 2015-13-01 at 10:22:34 UTC, Anshuman Khandual wrote: >> This patch adds a test case for the system wide DSCR default >> value, which when changed through it's sysfs interface must >> be visible to all threads reading DSCR either through the >> privilege state SPR or the problem state SPR. The DSCR value >> change should be immediate as well. > > ... > >> + >> +/* Default DSCR access */ >> +unsigned long get_default_dscr(void) >> +{ >> + int fd = -1; >> + char buf[16]; >> + unsigned long val; >> + >> + if (fd == -1) { >> + fd = open(DSCR_DEFAULT, O_RDONLY); >> + if (fd == -1) { >> + perror("open() failed\n"); >> + exit(1); >> + } >> + } >> + memset(buf, 0, sizeof(buf)); >> + lseek(fd, 0, SEEK_SET); >> + read(fd, buf, sizeof(buf)); > Normally, I build the test cases like $cd tools/testing/selftests/powerpc/ $make dscr with these compiler flags "-Wall -O2 -flto -Wall -Werror" which is still working for me. Then I figured out that the read and write declaration in unistd.h header file has "_wur" in it. extern ssize_t read (int __fd, void *__buf, size_t __nbytes) __wur; extern ssize_t write (int __fd, const void *__buf, size_t __n) __wur; Then some how the compiler (GCC 4.8.3) is not complaining about it. > > This and the other tests are failing to build: > > In file included from dscr_default_test.c:16:0: > dscr.h: In function ‘get_default_dscr’: > dscr.h:93:6: error: ignoring return value of ‘read’, declared with attribute warn_unused_result [-Werror=unused-result] > read(fd, buf, sizeof(buf)); > ^ > dscr.h: In function ‘set_default_dscr’: > dscr.h:112:7: error: ignoring return value of ‘write’, declared with attribute warn_unused_result [-Werror=unused-result] > write(fd, buf, strlen(buf)); > ^ > cc1: all warnings being treated as errors Anyways, I can change the header file helper functions if you would like. BTW, the patch series does not apply as it is and requires rebasing. Would send out a new version of it.
On 04/09/2015 04:01 PM, Anshuman Khandual wrote: > On 03/27/2015 05:31 PM, Michael Ellerman wrote: >> On Tue, 2015-13-01 at 10:22:34 UTC, Anshuman Khandual wrote: >>> This patch adds a test case for the system wide DSCR default >>> value, which when changed through it's sysfs interface must >>> be visible to all threads reading DSCR either through the >>> privilege state SPR or the problem state SPR. The DSCR value >>> change should be immediate as well. >> >> ... >> >>> + >>> +/* Default DSCR access */ >>> +unsigned long get_default_dscr(void) >>> +{ >>> + int fd = -1; >>> + char buf[16]; >>> + unsigned long val; >>> + >>> + if (fd == -1) { >>> + fd = open(DSCR_DEFAULT, O_RDONLY); >>> + if (fd == -1) { >>> + perror("open() failed\n"); >>> + exit(1); >>> + } >>> + } >>> + memset(buf, 0, sizeof(buf)); >>> + lseek(fd, 0, SEEK_SET); >>> + read(fd, buf, sizeof(buf)); >> > > Normally, I build the test cases like > > $cd tools/testing/selftests/powerpc/ > $make dscr > > with these compiler flags "-Wall -O2 -flto -Wall -Werror" which > is still working for me. Then I figured out that the read and > write declaration in unistd.h header file has "_wur" in it. > > extern ssize_t read (int __fd, void *__buf, size_t __nbytes) __wur; > extern ssize_t write (int __fd, const void *__buf, size_t __n) __wur; > > Then some how the compiler (GCC 4.8.3) is not complaining about it. > >> >> This and the other tests are failing to build: >> >> In file included from dscr_default_test.c:16:0: >> dscr.h: In function ‘get_default_dscr’: >> dscr.h:93:6: error: ignoring return value of ‘read’, declared with attribute warn_unused_result [-Werror=unused-result] >> read(fd, buf, sizeof(buf)); >> ^ >> dscr.h: In function ‘set_default_dscr’: >> dscr.h:112:7: error: ignoring return value of ‘write’, declared with attribute warn_unused_result [-Werror=unused-result] >> write(fd, buf, strlen(buf)); >> ^ >> cc1: all warnings being treated as errors > > Anyways, I can change the header file helper functions if you would like. > BTW, the patch series does not apply as it is and requires rebasing. Would > send out a new version of it. The rebased patch series works as expected like this version and all the tests pass. I would add a .gitignore file for this new test directory. Please let me know if there are other changes which need to be done. Thanks !!
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile index f6ff90a..1318883 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 copyloops mm tm primitives +TARGETS = pmu copyloops mm tm primitives dscr endif diff --git a/tools/testing/selftests/powerpc/dscr/Makefile b/tools/testing/selftests/powerpc/dscr/Makefile new file mode 100644 index 0000000..0aa90ab --- /dev/null +++ b/tools/testing/selftests/powerpc/dscr/Makefile @@ -0,0 +1,17 @@ +PROGS := dscr_default_test + +CFLAGS := $(CFLAGS) -lpthread + +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/dscr/dscr.h b/tools/testing/selftests/powerpc/dscr/dscr.h new file mode 100644 index 0000000..2e6535b --- /dev/null +++ b/tools/testing/selftests/powerpc/dscr/dscr.h @@ -0,0 +1,120 @@ +/* + * POWER Data Stream Control Register (DSCR) + * + * This header file contains helper functions and macros + * required for all the DSCR related test cases. + * + * Copyright (C) 2012 Anton Blanchard <anton@au.ibm.com>, IBM + * Copyright (C) 2015 Anshuman Khandual <khandual@linux.vnet.ibm.com>, IBM + * + * 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. + */ +#ifndef _SELFTESTS_POWERPC_DSCR_DSCR_H +#define _SELFTESTS_POWERPC_DSCR_DSCR_H + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <dirent.h> +#include <pthread.h> +#include <sched.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#include "utils.h" + +#define SPRN_DSCR 0x11 /* Privilege state SPR */ +#define SPRN_DSCR_USR 0x03 /* Problem state SPR */ +#define THREADS 100 /* Max threads */ +#define COUNT 100 /* Max iterations */ +#define DSCR_MAX 16 /* Max DSCR value */ +#define LEN_MAX 100 /* Max name length */ + +#define DSCR_DEFAULT "/sys/devices/system/cpu/dscr_default" +#define CPU_PATH "/sys/devices/system/cpu/" + +#define rmb() asm volatile("lwsync":::"memory") +#define wmb() asm volatile("lwsync":::"memory") + +#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) + +/* Prilvilege state DSCR access */ +inline unsigned long get_dscr(void) +{ + unsigned long ret; + + asm volatile("mfspr %0,%1" : "=r" (ret): "i" (SPRN_DSCR)); + + return ret; +} + +inline void set_dscr(unsigned long val) +{ + asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR)); +} + +/* Problem state DSCR access */ +inline unsigned long get_dscr_usr(void) +{ + unsigned long ret; + + asm volatile("mfspr %0,%1" : "=r" (ret): "i" (SPRN_DSCR_USR)); + + return ret; +} + +inline void set_dscr_usr(unsigned long val) +{ + asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR_USR)); +} + +/* Default DSCR access */ +unsigned long get_default_dscr(void) +{ + int fd = -1; + char buf[16]; + unsigned long val; + + if (fd == -1) { + fd = open(DSCR_DEFAULT, O_RDONLY); + if (fd == -1) { + perror("open() failed\n"); + exit(1); + } + } + memset(buf, 0, sizeof(buf)); + lseek(fd, 0, SEEK_SET); + read(fd, buf, sizeof(buf)); + sscanf(buf, "%lx", &val); + close(fd); + return val; +} + +void set_default_dscr(unsigned long val) +{ + int fd = -1; + char buf[16]; + + if (fd == -1) { + fd = open(DSCR_DEFAULT, O_RDWR); + if (fd == -1) { + perror("open() failed\n"); + exit(1); + } + } + sprintf(buf, "%lx\n", val); + write(fd, buf, strlen(buf)); + close(fd); +} + +double uniform_deviate(int seed) +{ + return seed * (1.0 / (RAND_MAX + 1.0)); +} +#endif /* _SELFTESTS_POWERPC_DSCR_DSCR_H */ diff --git a/tools/testing/selftests/powerpc/dscr/dscr_default_test.c b/tools/testing/selftests/powerpc/dscr/dscr_default_test.c new file mode 100644 index 0000000..fd8b7b9 --- /dev/null +++ b/tools/testing/selftests/powerpc/dscr/dscr_default_test.c @@ -0,0 +1,121 @@ +/* + * POWER Data Stream Control Register (DSCR) default test + * + * This test modifies the system wide default DSCR through + * it's sysfs interface and then verifies that all threads + * see the correct changed DSCR value immediately. + * + * Copyright (C) 2012 Anton Blanchard <anton@au.ibm.com>, IBM + * Copyright (C) 2015 Anshuman Khandual <khandual@linux.vnet.ibm.com>, IBM + * + * 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. + */ +#include "dscr.h" + +static unsigned long dscr; /* System DSCR default */ +static unsigned long sequence; +static unsigned long result[THREADS]; + +static void *do_test(void *in) +{ + unsigned long thread = (unsigned long)in; + unsigned long i; + + for (i = 0; i < COUNT; i++) { + unsigned long d, cur_dscr, cur_dscr_usr; + unsigned long s1, s2; + + s1 = ACCESS_ONCE(sequence); + if (s1 & 1) + continue; + rmb(); + + d = dscr; + cur_dscr = get_dscr(); + cur_dscr_usr = get_dscr_usr(); + + rmb(); + s2 = sequence; + + if (s1 != s2) + continue; + + if (cur_dscr != d) { + fprintf(stderr, "thread %ld kernel DSCR should be %ld " + "but is %ld\n", thread, d, cur_dscr); + result[thread] = 1; + pthread_exit(&result[thread]); + } + + if (cur_dscr_usr != d) { + fprintf(stderr, "thread %ld user DSCR should be %ld " + "but is %ld\n", thread, d, cur_dscr_usr); + result[thread] = 1; + pthread_exit(&result[thread]); + } + } + result[thread] = 0; + pthread_exit(&result[thread]); +} + +int test_body(void) +{ + pthread_t threads[THREADS]; + unsigned long i, *status[THREADS]; + + /* Initial DSCR default */ + dscr = 1; + set_default_dscr(dscr); + + /* Spawn all testing threads */ + for (i = 0; i < THREADS; i++) { + if (pthread_create(&threads[i], NULL, do_test, (void *)i)) { + perror("pthread_create() failed\n"); + exit(1); + } + } + + srand(getpid()); + + /* Keep changing the DSCR default */ + for (i = 0; i < COUNT; i++) { + double ret = uniform_deviate(rand()); + + if (ret < 0.0001) { + sequence++; + wmb(); + + dscr++; + if (dscr > DSCR_MAX) + dscr = 0; + + set_default_dscr(dscr); + + wmb(); + sequence++; + } + } + + /* Individual testing thread exit status */ + for (i = 0; i < THREADS; i++) { + if (pthread_join(threads[i], (void **)&(status[i]))) { + perror("pthread_join() failed\n"); + exit(1); + } + + if (*status[i]) { + printf("%ldth thread failed to join with %ld status\n", + i, *status[i]); + return 1; + } + } + return 0; +} + +int main(int argc, char *argv[]) +{ + return test_harness(test_body, "dscr_default_test"); +}
This patch adds a test case for the system wide DSCR default value, which when changed through it's sysfs interface must be visible to all threads reading DSCR either through the privilege state SPR or the problem state SPR. The DSCR value change should be immediate as well. Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com> --- tools/testing/selftests/powerpc/Makefile | 2 +- tools/testing/selftests/powerpc/dscr/Makefile | 17 +++ tools/testing/selftests/powerpc/dscr/dscr.h | 120 ++++++++++++++++++++ .../selftests/powerpc/dscr/dscr_default_test.c | 121 +++++++++++++++++++++ 4 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/powerpc/dscr/Makefile create mode 100644 tools/testing/selftests/powerpc/dscr/dscr.h create mode 100644 tools/testing/selftests/powerpc/dscr/dscr_default_test.c