* [PATCH 1/2] selftests/powerpc: Check for pthread errors in tm-unavailable @ 2017-11-21 7:17 Cyril Bur 2017-11-21 7:17 ` [PATCH 2/2] selftests/powerpc: Calculate spin time " Cyril Bur ` (2 more replies) 0 siblings, 3 replies; 8+ messages in thread From: Cyril Bur @ 2017-11-21 7:17 UTC (permalink / raw) To: linuxppc-dev; +Cc: leitao, gromero Signed-off-by: Cyril Bur <cyrilbur@gmail.com> --- .../testing/selftests/powerpc/tm/tm-unavailable.c | 43 +++++++++++++++++----- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/powerpc/tm/tm-unavailable.c b/tools/testing/selftests/powerpc/tm/tm-unavailable.c index 96c37f84ce54..e6a0fad2bfd0 100644 --- a/tools/testing/selftests/powerpc/tm/tm-unavailable.c +++ b/tools/testing/selftests/powerpc/tm/tm-unavailable.c @@ -15,6 +15,7 @@ */ #define _GNU_SOURCE +#include <error.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -33,6 +34,11 @@ #define VSX_UNA_EXCEPTION 2 #define NUM_EXCEPTIONS 3 +#define err_at_line(status, errnum, format, ...) \ + error_at_line(status, errnum, __FILE__, __LINE__, format ##__VA_ARGS__) + +#define pr_warn(code, format, ...) err_at_line(0, code, format, ##__VA_ARGS__) +#define pr_err(code, format, ...) err_at_line(1, code, format, ##__VA_ARGS__) struct Flags { int touch_fp; @@ -303,10 +309,19 @@ void test_fp_vec(int fp, int vec, pthread_attr_t *attr) * checking if the failure cause is the one we expect. */ do { + int rc; + /* Bind 'ping' to CPU 0, as specified in 'attr'. */ - pthread_create(&t0, attr, ping, (void *) &flags); - pthread_setname_np(t0, "ping"); - pthread_join(t0, &ret_value); + rc = pthread_create(&t0, attr, ping, (void *) &flags); + if (rc) + pr_err(rc, "pthread_create()"); + rc = pthread_setname_np(t0, "ping"); + if (rc) + pr_warn(rc, "pthread_setname_np"); + rc = pthread_join(t0, &ret_value); + if (rc) + pr_err(rc, "pthread_join"); + retries--; } while (ret_value != NULL && retries); @@ -320,7 +335,7 @@ void test_fp_vec(int fp, int vec, pthread_attr_t *attr) int main(int argc, char **argv) { - int exception; /* FP = 0, VEC = 1, VSX = 2 */ + int rc, exception; /* FP = 0, VEC = 1, VSX = 2 */ pthread_t t1; pthread_attr_t attr; cpu_set_t cpuset; @@ -330,13 +345,23 @@ int main(int argc, char **argv) CPU_SET(0, &cpuset); /* Init pthread attribute. */ - pthread_attr_init(&attr); + rc = pthread_attr_init(&attr); + if (rc) + pr_err(rc, "pthread_attr_init()"); /* Set CPU 0 mask into the pthread attribute. */ - pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset); - - pthread_create(&t1, &attr /* Bind 'pong' to CPU 0 */, pong, NULL); - pthread_setname_np(t1, "pong"); /* Name it for systemtap convenience */ + rc = pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset); + if (rc) + pr_err(rc, "pthread_attr_setaffinity_np()"); + + rc = pthread_create(&t1, &attr /* Bind 'pong' to CPU 0 */, pong, NULL); + if (rc) + pr_err(rc, "pthread_create()"); + + /* Name it for systemtap convenience */ + rc = pthread_setname_np(t1, "pong"); + if (rc) + pr_warn(rc, "pthread_create()"); flags.result = 0; -- 2.15.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/2] selftests/powerpc: Calculate spin time in tm-unavailable 2017-11-21 7:17 [PATCH 1/2] selftests/powerpc: Check for pthread errors in tm-unavailable Cyril Bur @ 2017-11-21 7:17 ` Cyril Bur 2017-11-21 13:31 ` Gustavo Romero 2017-11-21 12:56 ` [PATCH 1/2] selftests/powerpc: Check for pthread errors " Gustavo Romero 2017-12-12 11:39 ` [1/2] " Michael Ellerman 2 siblings, 1 reply; 8+ messages in thread From: Cyril Bur @ 2017-11-21 7:17 UTC (permalink / raw) To: linuxppc-dev; +Cc: leitao, gromero Currently the tm-unavailable test spins for a fixed amount of time in an attempt to ensure the FPU/VMX/VSX facilities are off. This value was experimentally tested to be long enough. Problems may arise if kernel heuristics were to change. This patch should future proof this test. Signed-off-by: Cyril Bur <cyrilbur@gmail.com> --- Because the test no longer needs to use such a conservative time for the busy wait, it actually runs much faster. .../testing/selftests/powerpc/tm/tm-unavailable.c | 92 ++++++++++++++++++++-- 1 file changed, 84 insertions(+), 8 deletions(-) diff --git a/tools/testing/selftests/powerpc/tm/tm-unavailable.c b/tools/testing/selftests/powerpc/tm/tm-unavailable.c index e6a0fad2bfd0..54aeb7a7fbb1 100644 --- a/tools/testing/selftests/powerpc/tm/tm-unavailable.c +++ b/tools/testing/selftests/powerpc/tm/tm-unavailable.c @@ -33,6 +33,11 @@ #define VEC_UNA_EXCEPTION 1 #define VSX_UNA_EXCEPTION 2 +#define ERR_RETRY 1 +#define ERR_ADJUST 2 + +#define COUNTER_INCREMENT (0x1000000) + #define NUM_EXCEPTIONS 3 #define err_at_line(status, errnum, format, ...) \ error_at_line(status, errnum, __FILE__, __LINE__, format ##__VA_ARGS__) @@ -45,6 +50,7 @@ struct Flags { int touch_vec; int result; int exception; + uint64_t counter; } flags; bool expecting_failure(void) @@ -87,14 +93,12 @@ void *ping(void *input) * Expected values for vs0 and vs32 after a TM failure. They must never * change, otherwise they got corrupted. */ + long rc = 0; uint64_t high_vs0 = 0x5555555555555555; uint64_t low_vs0 = 0xffffffffffffffff; uint64_t high_vs32 = 0x5555555555555555; uint64_t low_vs32 = 0xffffffffffffffff; - /* Counter for busy wait */ - uint64_t counter = 0x1ff000000; - /* * Variable to keep a copy of CR register content taken just after we * leave the transactional state. @@ -217,7 +221,7 @@ void *ping(void *input) [ex_fp] "i" (FP_UNA_EXCEPTION), [ex_vec] "i" (VEC_UNA_EXCEPTION), [ex_vsx] "i" (VSX_UNA_EXCEPTION), - [counter] "r" (counter) + [counter] "r" (flags.counter) : "cr0", "ctr", "v10", "vs0", "vs10", "vs3", "vs32", "vs33", "vs34", "fr10" @@ -232,14 +236,14 @@ void *ping(void *input) if (expecting_failure() && !is_failure(cr_)) { printf("\n\tExpecting the transaction to fail, %s", "but it didn't\n\t"); - flags.result++; + rc = ERR_ADJUST; } /* Check if we were not expecting a failure and a it occurred. */ if (!expecting_failure() && is_failure(cr_)) { printf("\n\tUnexpected transaction failure 0x%02lx\n\t", failure_code()); - return (void *) -1; + rc = ERR_RETRY; } /* @@ -249,7 +253,7 @@ void *ping(void *input) if (is_failure(cr_) && !failure_is_unavailable()) { printf("\n\tUnexpected failure cause 0x%02lx\n\t", failure_code()); - return (void *) -1; + rc = ERR_RETRY; } /* 0x4 is a success and 0xa is a fail. See comment in is_failure(). */ @@ -276,7 +280,7 @@ void *ping(void *input) putchar('\n'); - return NULL; + return (void *)rc; } /* Thread to force context switch */ @@ -291,6 +295,55 @@ void *pong(void *not_used) sched_yield(); } +static void flags_set_counter(struct Flags *flags) +{ + uint64_t cr_; + int count = 0; + + do { + if (count == 0) + printf("\tTrying 0x%08" PRIx64 "... ", flags->counter); + else + printf("%d, ", count); + fflush(stdout); + asm ( + /* + * Wait an amount of context switches so + * load_fp and load_vec overflow and MSR.FP, + * MSR.VEC, and MSR.VSX become zero (off). + */ + " mtctr %[counter] ;" + + /* Decrement CTR branch if CTR non zero. */ + "1: bdnz 1b ;" + " tbegin. ;" + " beq tfail ;" + + /* Get a facility unavailable */ + " fadd 10, 10, 10 ;" + " tend. ;" + "tfail: ;" + + /* + * Give CR back to C so that it can check what + * happened. + */ + " mfcr %[cr_] ;" + + : [cr_] "+r" (cr_) + : [counter] "r" (flags->counter) + : "cr0", "ctr", "fr10" + ); + count++; + if (!is_failure(cr_) || !failure_is_unavailable()) { + count = 0; + flags->counter += COUNTER_INCREMENT; + putchar('\n'); + } + } while (count < 3); + printf("3\n"); +} + /* Function that creates a thread and launches the "ping" task. */ void test_fp_vec(int fp, int vec, pthread_attr_t *attr) { @@ -322,6 +375,17 @@ void test_fp_vec(int fp, int vec, pthread_attr_t *attr) if (rc) pr_err(rc, "pthread_join"); + if ((long)ret_value == ERR_ADJUST) { + printf("Adjusting the facility unavailable spin time...\n"); + /* + * Be a bit more agressive just now - we'd + * really like to have it work + */ + flags.counter += (2 * COUNTER_INCREMENT); + flags_set_counter(&flags); + printf("Now using 0x%08" PRIx64 "\n", flags.counter); + } + retries--; } while (ret_value != NULL && retries); @@ -340,6 +404,18 @@ int main(int argc, char **argv) pthread_attr_t attr; cpu_set_t cpuset; + /* + * Default counter for busy wait. + * 0x18000000 is a good baseline determined by experimentation + * on a POWER8 + * The autodetecting code will bump it up if it too low. + */ + flags.counter = 0x18000000; + + printf("Testing required spin time required for facility unavailable...\n"); + flags_set_counter(&flags); + printf("Spin time required for a reliable facility unavailable TM failure: 0x%" PRIx64 "\n", + flags.counter); /* Set only CPU 0 in the mask. Both threads will be bound to CPU 0. */ CPU_ZERO(&cpuset); CPU_SET(0, &cpuset); -- 2.15.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] selftests/powerpc: Calculate spin time in tm-unavailable 2017-11-21 7:17 ` [PATCH 2/2] selftests/powerpc: Calculate spin time " Cyril Bur @ 2017-11-21 13:31 ` Gustavo Romero 2017-11-21 23:41 ` Cyril Bur 0 siblings, 1 reply; 8+ messages in thread From: Gustavo Romero @ 2017-11-21 13:31 UTC (permalink / raw) To: Cyril Bur, linuxppc-dev; +Cc: leitao Hi Cyril, On 21-11-2017 05:17, Cyril Bur wrote: > Currently the tm-unavailable test spins for a fixed amount of time in > an attempt to ensure the FPU/VMX/VSX facilities are off. This value was > experimentally tested to be long enough. > > Problems may arise if kernel heuristics were to change. This patch > should future proof this test. I've tried it on a VM running on '4.14.0-rc7' and apparently it gets stuck / pretty slow on calibration, since it ran ~7m without finding the correct value (before it would take about 3m), like: $ time ./tm-unavailable Testing required spin time required for facility unavailable... Trying 0x18000000... Trying 0x19000000... Trying 0x1a000000... ... Trying 0xfd000000... ^C real 7m15.304s user 7m15.291s sys 0m0.004s Trying it on a BM running on '4.13.0-rc2' it indeed found an initial value for the timeout but for some reason the value was not sufficient for the subsequent tests and the value raised more and more (I understand that it's an expected behavior tho). Even tho it runs about half the time (~3m, good!) but I think the output could be little bit less "overloaded": $ ./tm-unavailable Testing required spin time required for facility unavailable... Trying 0x18000000... Trying 0x19000000... Trying 0x1a000000... Trying 0x1b000000... Trying 0x1c000000... Trying 0x1d000000... Trying 0x1e000000... Trying 0x1f000000... 1, 2, 3 Spin time required for a reliable facility unavailable TM failure: 0x1f000000 Checking if FP/VEC registers are sane after a FP unavailable exception... If MSR.FP=0 MSR.VEC=0: Expecting the transaction to fail, but it didn't FP ok VEC ok Adjusting the facility unavailable spin time... Trying 0x21000000... 1, 2, 3 Now using 0x21000000 If MSR.FP=0 MSR.VEC=0: Expecting the transaction to fail, but it didn't FP ok VEC ok Adjusting the facility unavailable spin time... Trying 0x23000000... 1, 2, 3 Now using 0x23000000 If MSR.FP=1 MSR.VEC=0: FP ok VEC ok If MSR.FP=0 MSR.VEC=1: Expecting the transaction to fail, but it didn't FP ok VEC ok Now using 0x47000000 ... So, putting output question aside, are you getting a different result on VM, i.e. did you notice if it got stuck/pretty slow? Regards, Gustavo > Signed-off-by: Cyril Bur <cyrilbur@gmail.com> > --- > Because the test no longer needs to use such a conservative time for > the busy wait, it actually runs much faster. > > > .../testing/selftests/powerpc/tm/tm-unavailable.c | 92 ++++++++++++++++++++-- > 1 file changed, 84 insertions(+), 8 deletions(-) > > diff --git a/tools/testing/selftests/powerpc/tm/tm-unavailable.c b/tools/testing/selftests/powerpc/tm/tm-unavailable.c > index e6a0fad2bfd0..54aeb7a7fbb1 100644 > --- a/tools/testing/selftests/powerpc/tm/tm-unavailable.c > +++ b/tools/testing/selftests/powerpc/tm/tm-unavailable.c > @@ -33,6 +33,11 @@ > #define VEC_UNA_EXCEPTION 1 > #define VSX_UNA_EXCEPTION 2 > > +#define ERR_RETRY 1 > +#define ERR_ADJUST 2 > + > +#define COUNTER_INCREMENT (0x1000000) > + > #define NUM_EXCEPTIONS 3 > #define err_at_line(status, errnum, format, ...) \ > error_at_line(status, errnum, __FILE__, __LINE__, format ##__VA_ARGS__) > @@ -45,6 +50,7 @@ struct Flags { > int touch_vec; > int result; > int exception; > + uint64_t counter; > } flags; > > bool expecting_failure(void) > @@ -87,14 +93,12 @@ void *ping(void *input) > * Expected values for vs0 and vs32 after a TM failure. They must never > * change, otherwise they got corrupted. > */ > + long rc = 0; > uint64_t high_vs0 = 0x5555555555555555; > uint64_t low_vs0 = 0xffffffffffffffff; > uint64_t high_vs32 = 0x5555555555555555; > uint64_t low_vs32 = 0xffffffffffffffff; > > - /* Counter for busy wait */ > - uint64_t counter = 0x1ff000000; > - > /* > * Variable to keep a copy of CR register content taken just after we > * leave the transactional state. > @@ -217,7 +221,7 @@ void *ping(void *input) > [ex_fp] "i" (FP_UNA_EXCEPTION), > [ex_vec] "i" (VEC_UNA_EXCEPTION), > [ex_vsx] "i" (VSX_UNA_EXCEPTION), > - [counter] "r" (counter) > + [counter] "r" (flags.counter) > > : "cr0", "ctr", "v10", "vs0", "vs10", "vs3", "vs32", "vs33", > "vs34", "fr10" > @@ -232,14 +236,14 @@ void *ping(void *input) > if (expecting_failure() && !is_failure(cr_)) { > printf("\n\tExpecting the transaction to fail, %s", > "but it didn't\n\t"); > - flags.result++; > + rc = ERR_ADJUST; > } > > /* Check if we were not expecting a failure and a it occurred. */ > if (!expecting_failure() && is_failure(cr_)) { > printf("\n\tUnexpected transaction failure 0x%02lx\n\t", > failure_code()); > - return (void *) -1; > + rc = ERR_RETRY; > } > > /* > @@ -249,7 +253,7 @@ void *ping(void *input) > if (is_failure(cr_) && !failure_is_unavailable()) { > printf("\n\tUnexpected failure cause 0x%02lx\n\t", > failure_code()); > - return (void *) -1; > + rc = ERR_RETRY; > } > > /* 0x4 is a success and 0xa is a fail. See comment in is_failure(). */ > @@ -276,7 +280,7 @@ void *ping(void *input) > > putchar('\n'); > > - return NULL; > + return (void *)rc; > } > > /* Thread to force context switch */ > @@ -291,6 +295,55 @@ void *pong(void *not_used) > sched_yield(); > } > > +static void flags_set_counter(struct Flags *flags) > +{ > + uint64_t cr_; > + int count = 0; > + > + do { > + if (count == 0) > + printf("\tTrying 0x%08" PRIx64 "... ", flags->counter); > + else > + printf("%d, ", count); > + fflush(stdout); > + asm ( > + /* > + * Wait an amount of context switches so > + * load_fp and load_vec overflow and MSR.FP, > + * MSR.VEC, and MSR.VSX become zero (off). > + */ > + " mtctr %[counter] ;" > + > + /* Decrement CTR branch if CTR non zero. */ > + "1: bdnz 1b ;" > + " tbegin. ;" > + " beq tfail ;" > + > + /* Get a facility unavailable */ > + " fadd 10, 10, 10 ;" > + " tend. ;" > + "tfail: ;" > + > + /* > + * Give CR back to C so that it can check what > + * happened. > + */ > + " mfcr %[cr_] ;" > + > + : [cr_] "+r" (cr_) > + : [counter] "r" (flags->counter) > + : "cr0", "ctr", "fr10" > + ); > + count++; > + if (!is_failure(cr_) || !failure_is_unavailable()) { > + count = 0; > + flags->counter += COUNTER_INCREMENT; > + putchar('\n'); > + } > + } while (count < 3); > + printf("3\n"); > +} > + > /* Function that creates a thread and launches the "ping" task. */ > void test_fp_vec(int fp, int vec, pthread_attr_t *attr) > { > @@ -322,6 +375,17 @@ void test_fp_vec(int fp, int vec, pthread_attr_t *attr) > if (rc) > pr_err(rc, "pthread_join"); > > + if ((long)ret_value == ERR_ADJUST) { > + printf("Adjusting the facility unavailable spin time...\n"); > + /* > + * Be a bit more agressive just now - we'd > + * really like to have it work > + */ > + flags.counter += (2 * COUNTER_INCREMENT); > + flags_set_counter(&flags); > + printf("Now using 0x%08" PRIx64 "\n", flags.counter); > + } > + > retries--; > } while (ret_value != NULL && retries); > > @@ -340,6 +404,18 @@ int main(int argc, char **argv) > pthread_attr_t attr; > cpu_set_t cpuset; > > + /* > + * Default counter for busy wait. > + * 0x18000000 is a good baseline determined by experimentation > + * on a POWER8 > + * The autodetecting code will bump it up if it too low. > + */ > + flags.counter = 0x18000000; > + > + printf("Testing required spin time required for facility unavailable...\n"); > + flags_set_counter(&flags); > + printf("Spin time required for a reliable facility unavailable TM failure: 0x%" PRIx64 "\n", > + flags.counter); > /* Set only CPU 0 in the mask. Both threads will be bound to CPU 0. */ > CPU_ZERO(&cpuset); > CPU_SET(0, &cpuset); > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] selftests/powerpc: Calculate spin time in tm-unavailable 2017-11-21 13:31 ` Gustavo Romero @ 2017-11-21 23:41 ` Cyril Bur 2017-12-11 2:02 ` Michael Ellerman 0 siblings, 1 reply; 8+ messages in thread From: Cyril Bur @ 2017-11-21 23:41 UTC (permalink / raw) To: Gustavo Romero, linuxppc-dev; +Cc: leitao On Tue, 2017-11-21 at 11:31 -0200, Gustavo Romero wrote: > Hi Cyril, > > On 21-11-2017 05:17, Cyril Bur wrote: > > Currently the tm-unavailable test spins for a fixed amount of time in > > an attempt to ensure the FPU/VMX/VSX facilities are off. This value was > > experimentally tested to be long enough. > > > > Problems may arise if kernel heuristics were to change. This patch > > should future proof this test. > > I've tried it on a VM running on '4.14.0-rc7' and apparently it gets stuck > pretty slow on calibration, since it ran ~7m without finding the correct value > (before it would take about 3m), like: > > $ time ./tm-unavailable > Testing required spin time required for facility unavailable... > Trying 0x18000000... > Trying 0x19000000... > Trying 0x1a000000... > ... > Trying 0xfd000000... ^C > > real 7m15.304s > user 7m15.291s > sys 0m0.004s > Interesting! I didn't test in a VM. I guess hypervisor switching completely changes the heuristic. Ok I'll have to rethink. Maybe the increase should be a multiplier to get to a good state more quickly. > Trying it on a BM running on '4.13.0-rc2' it indeed found an initial value for > the timeout but for some reason the value was not sufficient for the subsequent > tests and the value raised more and more (I understand that it's an expected > behavior tho). Even tho it runs about half the time (~3m, good!) but I think the > output could be little bit less "overloaded": > Happy to put some (or all) of that output inside if (DEBUG) > $ ./tm-unavailable > Testing required spin time required for facility unavailable... > Trying 0x18000000... > Trying 0x19000000... > Trying 0x1a000000... > Trying 0x1b000000... > Trying 0x1c000000... > Trying 0x1d000000... > Trying 0x1e000000... > Trying 0x1f000000... 1, 2, 3 > Spin time required for a reliable facility unavailable TM failure: 0x1f000000 > Checking if FP/VEC registers are sane after a FP unavailable exception... > If MSR.FP=0 MSR.VEC=0: > Expecting the transaction to fail, but it didn't > FP ok VEC ok > Adjusting the facility unavailable spin time... > Trying 0x21000000... 1, 2, 3 > Now using 0x21000000 > If MSR.FP=0 MSR.VEC=0: > Expecting the transaction to fail, but it didn't > FP ok VEC ok > Adjusting the facility unavailable spin time... > Trying 0x23000000... 1, 2, 3 > Now using 0x23000000 > If MSR.FP=1 MSR.VEC=0: FP ok VEC ok > If MSR.FP=0 MSR.VEC=1: > Expecting the transaction to fail, but it didn't > FP ok VEC ok > Now using 0x47000000 > ... > > So, putting output question aside, are you getting a different result on VM, > i.e. did you notice if it got stuck/pretty slow? > > > Regards, > Gustavo > > > Signed-off-by: Cyril Bur <cyrilbur@gmail.com> > > --- > > Because the test no longer needs to use such a conservative time for > > the busy wait, it actually runs much faster. > > > > > > .../testing/selftests/powerpc/tm/tm-unavailable.c | 92 ++++++++++++++++++++-- > > 1 file changed, 84 insertions(+), 8 deletions(-) > > > > diff --git a/tools/testing/selftests/powerpc/tm/tm-unavailable.c b/tools/testing/selftests/powerpc/tm/tm-unavailable.c > > index e6a0fad2bfd0..54aeb7a7fbb1 100644 > > --- a/tools/testing/selftests/powerpc/tm/tm-unavailable.c > > +++ b/tools/testing/selftests/powerpc/tm/tm-unavailable.c > > @@ -33,6 +33,11 @@ > > #define VEC_UNA_EXCEPTION 1 > > #define VSX_UNA_EXCEPTION 2 > > > > +#define ERR_RETRY 1 > > +#define ERR_ADJUST 2 > > + > > +#define COUNTER_INCREMENT (0x1000000) > > + > > #define NUM_EXCEPTIONS 3 > > #define err_at_line(status, errnum, format, ...) \ > > error_at_line(status, errnum, __FILE__, __LINE__, format ##__VA_ARGS__) > > @@ -45,6 +50,7 @@ struct Flags { > > int touch_vec; > > int result; > > int exception; > > + uint64_t counter; > > } flags; > > > > bool expecting_failure(void) > > @@ -87,14 +93,12 @@ void *ping(void *input) > > * Expected values for vs0 and vs32 after a TM failure. They must never > > * change, otherwise they got corrupted. > > */ > > + long rc = 0; > > uint64_t high_vs0 = 0x5555555555555555; > > uint64_t low_vs0 = 0xffffffffffffffff; > > uint64_t high_vs32 = 0x5555555555555555; > > uint64_t low_vs32 = 0xffffffffffffffff; > > > > - /* Counter for busy wait */ > > - uint64_t counter = 0x1ff000000; > > - > > /* > > * Variable to keep a copy of CR register content taken just after we > > * leave the transactional state. > > @@ -217,7 +221,7 @@ void *ping(void *input) > > [ex_fp] "i" (FP_UNA_EXCEPTION), > > [ex_vec] "i" (VEC_UNA_EXCEPTION), > > [ex_vsx] "i" (VSX_UNA_EXCEPTION), > > - [counter] "r" (counter) > > + [counter] "r" (flags.counter) > > > > : "cr0", "ctr", "v10", "vs0", "vs10", "vs3", "vs32", "vs33", > > "vs34", "fr10" > > @@ -232,14 +236,14 @@ void *ping(void *input) > > if (expecting_failure() && !is_failure(cr_)) { > > printf("\n\tExpecting the transaction to fail, %s", > > "but it didn't\n\t"); > > - flags.result++; > > + rc = ERR_ADJUST; > > } > > > > /* Check if we were not expecting a failure and a it occurred. */ > > if (!expecting_failure() && is_failure(cr_)) { > > printf("\n\tUnexpected transaction failure 0x%02lx\n\t", > > failure_code()); > > - return (void *) -1; > > + rc = ERR_RETRY; > > } > > > > /* > > @@ -249,7 +253,7 @@ void *ping(void *input) > > if (is_failure(cr_) && !failure_is_unavailable()) { > > printf("\n\tUnexpected failure cause 0x%02lx\n\t", > > failure_code()); > > - return (void *) -1; > > + rc = ERR_RETRY; > > } > > > > /* 0x4 is a success and 0xa is a fail. See comment in is_failure(). */ > > @@ -276,7 +280,7 @@ void *ping(void *input) > > > > putchar('\n'); > > > > - return NULL; > > + return (void *)rc; > > } > > > > /* Thread to force context switch */ > > @@ -291,6 +295,55 @@ void *pong(void *not_used) > > sched_yield(); > > } > > > > +static void flags_set_counter(struct Flags *flags) > > +{ > > + uint64_t cr_; > > + int count = 0; > > + > > + do { > > + if (count == 0) > > + printf("\tTrying 0x%08" PRIx64 "... ", flags->counter); > > + else > > + printf("%d, ", count); > > + fflush(stdout); > > + asm ( > > + /* > > + * Wait an amount of context switches so > > + * load_fp and load_vec overflow and MSR.FP, > > + * MSR.VEC, and MSR.VSX become zero (off). > > + */ > > + " mtctr %[counter] ;" > > + > > + /* Decrement CTR branch if CTR non zero. */ > > + "1: bdnz 1b ;" > > + " tbegin. ;" > > + " beq tfail ;" > > + > > + /* Get a facility unavailable */ > > + " fadd 10, 10, 10 ;" > > + " tend. ;" > > + "tfail: ;" > > + > > + /* > > + * Give CR back to C so that it can check what > > + * happened. > > + */ > > + " mfcr %[cr_] ;" > > + > > + : [cr_] "+r" (cr_) > > + : [counter] "r" (flags->counter) > > + : "cr0", "ctr", "fr10" > > + ); > > + count++; > > + if (!is_failure(cr_) || !failure_is_unavailable()) { > > + count = 0; > > + flags->counter += COUNTER_INCREMENT; > > + putchar('\n'); > > + } > > + } while (count < 3); > > + printf("3\n"); > > +} > > + > > /* Function that creates a thread and launches the "ping" task. */ > > void test_fp_vec(int fp, int vec, pthread_attr_t *attr) > > { > > @@ -322,6 +375,17 @@ void test_fp_vec(int fp, int vec, pthread_attr_t *attr) > > if (rc) > > pr_err(rc, "pthread_join"); > > > > + if ((long)ret_value == ERR_ADJUST) { > > + printf("Adjusting the facility unavailable spin time...\n"); > > + /* > > + * Be a bit more agressive just now - we'd > > + * really like to have it work > > + */ > > + flags.counter += (2 * COUNTER_INCREMENT); > > + flags_set_counter(&flags); > > + printf("Now using 0x%08" PRIx64 "\n", flags.counter); > > + } > > + > > retries--; > > } while (ret_value != NULL && retries); > > > > @@ -340,6 +404,18 @@ int main(int argc, char **argv) > > pthread_attr_t attr; > > cpu_set_t cpuset; > > > > + /* > > + * Default counter for busy wait. > > + * 0x18000000 is a good baseline determined by experimentation > > + * on a POWER8 > > + * The autodetecting code will bump it up if it too low. > > + */ > > + flags.counter = 0x18000000; > > + > > + printf("Testing required spin time required for facility unavailable...\n"); > > + flags_set_counter(&flags); > > + printf("Spin time required for a reliable facility unavailable TM failure: 0x%" PRIx64 "\n", > > + flags.counter); > > /* Set only CPU 0 in the mask. Both threads will be bound to CPU 0. */ > > CPU_ZERO(&cpuset); > > CPU_SET(0, &cpuset); > > > > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] selftests/powerpc: Calculate spin time in tm-unavailable 2017-11-21 23:41 ` Cyril Bur @ 2017-12-11 2:02 ` Michael Ellerman 2017-12-11 3:40 ` Cyril Bur 0 siblings, 1 reply; 8+ messages in thread From: Michael Ellerman @ 2017-12-11 2:02 UTC (permalink / raw) To: Cyril Bur, Gustavo Romero, linuxppc-dev; +Cc: leitao Cyril Bur <cyrilbur@gmail.com> writes: > On Tue, 2017-11-21 at 11:31 -0200, Gustavo Romero wrote: >> Hi Cyril, >> >> On 21-11-2017 05:17, Cyril Bur wrote: >> > Currently the tm-unavailable test spins for a fixed amount of time in >> > an attempt to ensure the FPU/VMX/VSX facilities are off. This value was >> > experimentally tested to be long enough. >> > >> > Problems may arise if kernel heuristics were to change. This patch >> > should future proof this test. >> >> I've tried it on a VM running on '4.14.0-rc7' and apparently it gets stuck >> pretty slow on calibration, since it ran ~7m without finding the correct value >> (before it would take about 3m), like: >> >> $ time ./tm-unavailable >> Testing required spin time required for facility unavailable... >> Trying 0x18000000... >> Trying 0x19000000... >> Trying 0x1a000000... >> ... >> Trying 0xfd000000... ^C >> >> real 7m15.304s >> user 7m15.291s >> sys 0m0.004s >> > > Interesting! I didn't test in a VM. I guess hypervisor switching > completely changes the heuristic. Ok I'll have to rethink. > > Maybe the increase should be a multiplier to get to a good state more > quickly. Yeah this sucks in a VM: # /home/michael/tm-unavailable Testing required spin time required for facility unavailable... Trying 0x18000000... Trying 0x19000000... ... Trying 0x110000000... etc. I got sick of waiting for it, but it's causing my selftests job to time out so it must be taking > ~1 hour. cheers ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] selftests/powerpc: Calculate spin time in tm-unavailable 2017-12-11 2:02 ` Michael Ellerman @ 2017-12-11 3:40 ` Cyril Bur 0 siblings, 0 replies; 8+ messages in thread From: Cyril Bur @ 2017-12-11 3:40 UTC (permalink / raw) To: Michael Ellerman, Gustavo Romero, linuxppc-dev; +Cc: Breno Leitao [-- Attachment #1: Type: text/plain, Size: 1808 bytes --] On Mon, 2017-12-11 at 13:02 +1100, Michael Ellerman wrote: > Cyril Bur <cyrilbur@gmail.com> writes: > > > On Tue, 2017-11-21 at 11:31 -0200, Gustavo Romero wrote: > > > Hi Cyril, > > > > > > On 21-11-2017 05:17, Cyril Bur wrote: > > > > Currently the tm-unavailable test spins for a fixed amount of time in > > > > an attempt to ensure the FPU/VMX/VSX facilities are off. This value was > > > > experimentally tested to be long enough. > > > > > > > > Problems may arise if kernel heuristics were to change. This patch > > > > should future proof this test. > > > > > > I've tried it on a VM running on '4.14.0-rc7' and apparently it gets stuck > > > pretty slow on calibration, since it ran ~7m without finding the correct value > > > (before it would take about 3m), like: > > > > > > $ time ./tm-unavailable > > > Testing required spin time required for facility unavailable... > > > Trying 0x18000000... > > > Trying 0x19000000... > > > Trying 0x1a000000... > > > ... > > > Trying 0xfd000000... ^C > > > > > > real 7m15.304s > > > user 7m15.291s > > > sys 0m0.004s > > > > > > > Interesting! I didn't test in a VM. I guess hypervisor switching > > completely changes the heuristic. Ok I'll have to rethink. > > > > Maybe the increase should be a multiplier to get to a good state more > > quickly. > > Yeah this sucks in a VM: > > # /home/michael/tm-unavailable > Testing required spin time required for facility unavailable... > Trying 0x18000000... > Trying 0x19000000... > ... > Trying 0x110000000... > > etc. > > I got sick of waiting for it, but it's causing my selftests job to time > out so it must be taking > ~1 hour. > Yeah sorry, I'll see if I can come up with a better way for a VM. Needs a few more cycles from me. Cyril > cheers [-- Attachment #2: Type: text/html, Size: 14857 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] selftests/powerpc: Check for pthread errors in tm-unavailable 2017-11-21 7:17 [PATCH 1/2] selftests/powerpc: Check for pthread errors in tm-unavailable Cyril Bur 2017-11-21 7:17 ` [PATCH 2/2] selftests/powerpc: Calculate spin time " Cyril Bur @ 2017-11-21 12:56 ` Gustavo Romero 2017-12-12 11:39 ` [1/2] " Michael Ellerman 2 siblings, 0 replies; 8+ messages in thread From: Gustavo Romero @ 2017-11-21 12:56 UTC (permalink / raw) To: Cyril Bur, linuxppc-dev; +Cc: leitao Hi Cyril, Thanks for adding the checks! On 21-11-2017 05:17, Cyril Bur wrote: > Signed-off-by: Cyril Bur <cyrilbur@gmail.com> Signed-off-by: Gustavo Romero <gromero@linux.vnet.ibm.com> Cheers, Gustavo > --- > .../testing/selftests/powerpc/tm/tm-unavailable.c | 43 +++++++++++++++++----- > 1 file changed, 34 insertions(+), 9 deletions(-) > > diff --git a/tools/testing/selftests/powerpc/tm/tm-unavailable.c b/tools/testing/selftests/powerpc/tm/tm-unavailable.c > index 96c37f84ce54..e6a0fad2bfd0 100644 > --- a/tools/testing/selftests/powerpc/tm/tm-unavailable.c > +++ b/tools/testing/selftests/powerpc/tm/tm-unavailable.c > @@ -15,6 +15,7 @@ > */ > > #define _GNU_SOURCE > +#include <error.h> > #include <stdio.h> > #include <stdlib.h> > #include <unistd.h> > @@ -33,6 +34,11 @@ > #define VSX_UNA_EXCEPTION 2 > > #define NUM_EXCEPTIONS 3 > +#define err_at_line(status, errnum, format, ...) \ > + error_at_line(status, errnum, __FILE__, __LINE__, format ##__VA_ARGS__) > + > +#define pr_warn(code, format, ...) err_at_line(0, code, format, ##__VA_ARGS__) > +#define pr_err(code, format, ...) err_at_line(1, code, format, ##__VA_ARGS__) > > struct Flags { > int touch_fp; > @@ -303,10 +309,19 @@ void test_fp_vec(int fp, int vec, pthread_attr_t *attr) > * checking if the failure cause is the one we expect. > */ > do { > + int rc; > + > /* Bind 'ping' to CPU 0, as specified in 'attr'. */ > - pthread_create(&t0, attr, ping, (void *) &flags); > - pthread_setname_np(t0, "ping"); > - pthread_join(t0, &ret_value); > + rc = pthread_create(&t0, attr, ping, (void *) &flags); > + if (rc) > + pr_err(rc, "pthread_create()"); > + rc = pthread_setname_np(t0, "ping"); > + if (rc) > + pr_warn(rc, "pthread_setname_np"); > + rc = pthread_join(t0, &ret_value); > + if (rc) > + pr_err(rc, "pthread_join"); > + > retries--; > } while (ret_value != NULL && retries); > > @@ -320,7 +335,7 @@ void test_fp_vec(int fp, int vec, pthread_attr_t *attr) > > int main(int argc, char **argv) > { > - int exception; /* FP = 0, VEC = 1, VSX = 2 */ > + int rc, exception; /* FP = 0, VEC = 1, VSX = 2 */ > pthread_t t1; > pthread_attr_t attr; > cpu_set_t cpuset; > @@ -330,13 +345,23 @@ int main(int argc, char **argv) > CPU_SET(0, &cpuset); > > /* Init pthread attribute. */ > - pthread_attr_init(&attr); > + rc = pthread_attr_init(&attr); > + if (rc) > + pr_err(rc, "pthread_attr_init()"); > > /* Set CPU 0 mask into the pthread attribute. */ > - pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset); > - > - pthread_create(&t1, &attr /* Bind 'pong' to CPU 0 */, pong, NULL); > - pthread_setname_np(t1, "pong"); /* Name it for systemtap convenience */ > + rc = pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset); > + if (rc) > + pr_err(rc, "pthread_attr_setaffinity_np()"); > + > + rc = pthread_create(&t1, &attr /* Bind 'pong' to CPU 0 */, pong, NULL); > + if (rc) > + pr_err(rc, "pthread_create()"); > + > + /* Name it for systemtap convenience */ > + rc = pthread_setname_np(t1, "pong"); > + if (rc) > + pr_warn(rc, "pthread_create()"); > > flags.result = 0; > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [1/2] selftests/powerpc: Check for pthread errors in tm-unavailable 2017-11-21 7:17 [PATCH 1/2] selftests/powerpc: Check for pthread errors in tm-unavailable Cyril Bur 2017-11-21 7:17 ` [PATCH 2/2] selftests/powerpc: Calculate spin time " Cyril Bur 2017-11-21 12:56 ` [PATCH 1/2] selftests/powerpc: Check for pthread errors " Gustavo Romero @ 2017-12-12 11:39 ` Michael Ellerman 2 siblings, 0 replies; 8+ messages in thread From: Michael Ellerman @ 2017-12-12 11:39 UTC (permalink / raw) To: Cyril Bur, linuxppc-dev; +Cc: leitao, gromero On Tue, 2017-11-21 at 07:17:19 UTC, Cyril Bur wrote: > Signed-off-by: Cyril Bur <cyrilbur@gmail.com> > Signed-off-by: Gustavo Romero <gromero@linux.vnet.ibm.com> Applied to powerpc next, thanks. https://git.kernel.org/powerpc/c/5783ee6ec3d3323a04cc69764d57ca cheers ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2017-12-12 11:39 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2017-11-21 7:17 [PATCH 1/2] selftests/powerpc: Check for pthread errors in tm-unavailable Cyril Bur 2017-11-21 7:17 ` [PATCH 2/2] selftests/powerpc: Calculate spin time " Cyril Bur 2017-11-21 13:31 ` Gustavo Romero 2017-11-21 23:41 ` Cyril Bur 2017-12-11 2:02 ` Michael Ellerman 2017-12-11 3:40 ` Cyril Bur 2017-11-21 12:56 ` [PATCH 1/2] selftests/powerpc: Check for pthread errors " Gustavo Romero 2017-12-12 11:39 ` [1/2] " Michael Ellerman
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).