diff mbox

[V2,06/12] selftests, powerpc: Add test for system wide DSCR default

Message ID 1421144560-15901-7-git-send-email-khandual@linux.vnet.ibm.com (mailing list archive)
State Superseded
Delegated to: Michael Ellerman
Headers show

Commit Message

Anshuman Khandual Jan. 13, 2015, 10:22 a.m. UTC
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

Comments

Shuah Khan Jan. 13, 2015, 3:22 p.m. UTC | #1
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
Michael Ellerman Jan. 13, 2015, 11:44 p.m. UTC | #2
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
Dave Jones Jan. 20, 2015, 9:40 p.m. UTC | #3
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
Michael Ellerman Jan. 21, 2015, 6:51 a.m. UTC | #4
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
Michael Ellerman March 27, 2015, 12:01 p.m. UTC | #5
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
Anshuman Khandual April 9, 2015, 10:31 a.m. UTC | #6
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.
Anshuman Khandual April 9, 2015, 12:38 p.m. UTC | #7
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 mbox

Patch

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");
+}