Index: tools/tools/htm_torture/Makefile =================================================================== --- /dev/null +++ tools/tools/htm_torture/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ +# FreeBSD Makefile + +PROG = torture +CFLAGS += -Wno-pointer-to-int-cast -Wall -maltivec -mcpu=power8 +LDFLAGS += -lpthread +MAN = +SRCS = torture.c signal.c threads.c worker.c workload.c qs.c + +CC = gcc6 + +.include Index: tools/tools/htm_torture/qs.c =================================================================== --- /dev/null +++ tools/tools/htm_torture/qs.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2017 Breno Leitao, Gustavo Romero, IBM Corp. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +unsigned long *array; + +void Swap(unsigned long *a, unsigned long *b) +{ + int temp; + + temp = *a; + *a = *b; + *b = temp; +} + +void PartitionArray(unsigned long *a, int left, int right, int *PivotLoc) +{ + *PivotLoc = left; + + while(1) + { + while(*(a+(*PivotLoc)) <= *(a+right) && *PivotLoc != right) + { + right--; + } + if(*PivotLoc == right) + { + break; + } + else if(*(a+(*PivotLoc)) > *(a+right)) + { + Swap((a+(*PivotLoc)), (a+right)); + *PivotLoc = right; + left++; + } + + while(*(a+(*PivotLoc)) >= *(a+left) && *PivotLoc != left) + { + left++; + } + if(*PivotLoc == left) + { + break; + } + else if(*(a+(*PivotLoc)) < *(a+left)) { + Swap((a+(*PivotLoc)), (a+left)); + *PivotLoc = left; + right--; + } + } // end while(1) +} + +void QuickSort(unsigned long *a, int left, int right) +{ + if (left < right) { + int PivotLoc; + + PartitionArray(a, left, right, &PivotLoc); + QuickSort(a, left, PivotLoc-1); + QuickSort(a, PivotLoc+1, right); + } +} Index: tools/tools/htm_torture/signal.c =================================================================== --- /dev/null +++ tools/tools/htm_torture/signal.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017 Breno Leitao, Gustavo Romero, IBM Corp. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "torture.h" + +#define DEBUG +void signal_handler(int signo, siginfo_t *si, void *data) +{ +#ifdef DEBUG_SIGNAL + // Set a local pointer to uc. + ucontext_t *uc = (ucontext_t *)data; + + printf("* Received a SIGTRAP\n"); + printf("* si->si_addr = %p\n", si->si_addr); + printf("* uc->uc_mcontext.regs->nip: %p\n", + (void *) uc->uc_mcontext.regs->nip); + + uc->uc_mcontext.regs->nip += 4; // Skip illegal instruction. + uc->uc_mcontext.gp_regs[32] += 4; // Same as above ;-) + printf("x"); +#endif +} Index: tools/tools/htm_torture/threads.c =================================================================== --- /dev/null +++ tools/tools/htm_torture/threads.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017 Breno Leitao, Gustavo Romero, IBM Corp. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "torture.h" +void reinit_workers(void) { + num_used_threads = 0; +} + +void start_workers(uint64_t workload, uint64_t nr_workers) +{ + for (uint64_t i = 0; i < nr_workers; i++) { + pthread_create(&thread_pool[num_used_threads], + NULL, &worker, (void *) workload); + num_used_threads++; + } +} + +void join_workers(void) +{ + for (uint64_t i = 0; i < num_used_threads; i++) + pthread_join(thread_pool[i], NULL); + + reinit_workers(); +} Index: tools/tools/htm_torture/torture.h =================================================================== --- /dev/null +++ tools/tools/htm_torture/torture.h @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define _ asm +// Number of threads to randomly distribute each workload. +// It might be the case that for an equal or a small number +// of THREADS is set in comparison to the number of workloads, +// then it might be the case that some workload will not be +// set to run. +#define THREADS 450 +#define REPEAT 1 +#define MAX_WORKLOADS 20 + +// This is the array size to be ordered by workload7: uptsm_qsort. +#define ARRAY_SIZE 64 + +// Thi is the array pointer to be ordered by worload7: uptsm_qsort. +extern unsigned long *array; + +extern void scall(); +extern void fibonacci(); +extern void nop(); +extern void tabort(); +extern void ownqsort(); +extern void loop(); +extern void iloop(); +extern void utpsm_qsort(); +extern void illegal(); +extern void trap(); +extern void dscr(); + +// Array of workloads functions +void (*workloads[MAX_WORKLOADS])(); +// TODO: Create a structure to keep both together +char wname[MAX_WORKLOADS][1024]; + +// not TLS (.bss) +int nr_workloads; +long tm_fails; +long tm_commit; +int debug; + +pthread_t thread_pool[THREADS*MAX_WORKLOADS*4096]; +uint64_t num_used_threads; + +// Workload type +#define UNINIT -1 +#define FAIL -2 +#define NON_FAIL -3 +#define ALL -4 + + +void init_workers(void); +void start_workers(uint64_t, uint64_t); +void join_workers(void); + +extern void signal_handler(int signo, siginfo_t *si, void *data); +extern void *worker(void *arg); + +// #define DEBUG Index: tools/tools/htm_torture/torture.c =================================================================== --- /dev/null +++ tools/tools/htm_torture/torture.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2017 Breno Leitao, Gustavo Romero, IBM Corp. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "torture.h" + +void register_workload(void *func, char *description) +{ + workloads[nr_workloads] = func; + strncpy(&wname[nr_workloads][0], description, 1024); + + if (debug) + printf("Registering workload %d (%s)\n", + nr_workloads, description ? + description : "no description available"); + + nr_workloads++; +} + +void list_workloads() +{ + int i; + + for (i = 0 ; i < nr_workloads ; i++){ + printf("%d: : %s\n", i, (char *) &wname[i]); + } +} + +void set_workloads() +{ + memset(workloads, 0, MAX_WORKLOADS*sizeof(void *)); + nr_workloads = 0; + + register_workload(scall, "syscall"); + register_workload(fibonacci, "recursion"); + register_workload(nop, "nop"); + register_workload(tabort, "tabort."); + register_workload(ownqsort, "quicksort"); + register_workload(loop, "loop"); + register_workload(iloop, "infite loop"); + + // Preparation for workload7. TODO: improve argument passing to + // workloads like that. + array = (unsigned long *) calloc(ARRAY_SIZE, sizeof(unsigned long)); + + // Fill array with pseudo-random values. + for (uint64_t i = 0; i < ARRAY_SIZE; i++) array[i] = rand(); + + // Order array. + register_workload(utpsm_qsort, "utpsm_qsort"); + + register_workload(illegal, "illegal instruction"); + register_workload(trap, "trap"); + register_workload(dscr, "dscr"); + + printf("\n"); +} + +int main(int argc, char **argv) +{ + int runworkload = UNINIT; + int infinityrun = 0; + int nr_threads = THREADS; + int i; + // Parse opt + int opt; + // Install signal handler for all threads. + struct sigaction sa; + + // Debug initially disabled + debug = 0; + + printf("Hardware Transactional Memory Torture\n"); + printf("-------------------------------------\n"); + if (debug) { + printf("! = Transaction Failed but the VSX + VRSAVE registers were preserved\n"); + printf(". = Transaction Succeeded (in that case VSX + VRSAVE registers are not checked\n\n"); + } + + + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = signal_handler; + sigaction(SIGTRAP, &sa, NULL); + sigaction(SIGILL, &sa, NULL); + + set_workloads(); + + while ((opt = getopt(argc, argv, "vcfials:n:")) != -1) { + if (opt == 'l') { + //List all options + printf("Listing all workloads\n"); + list_workloads(); + exit(0); + } else if (opt == 'v') { + debug = 1; + } else if (opt == 'i') { + infinityrun = 1; + } else if (opt == 'f') { + runworkload = FAIL; + } else if (opt == 'c') { + runworkload = NON_FAIL; + } else if (opt == 's') { + int w = atoi(optarg); + if (w > nr_workloads) { + printf("Workload %d does not exist\n\n These are the available workloads:\n", w); + list_workloads(); + exit(2); + } + printf("Running just workload %d (%s) \n", w, + (char *) &wname[w]); + runworkload = atoi(optarg); + } else if (opt == 'a') { + printf("Running all workloads\n"); + runworkload = ALL; + } else if (opt == 'n') { + nr_threads = atoi(optarg); + } + } + + if (infinityrun && runworkload == UNINIT) + runworkload = ALL; + + if (runworkload == UNINIT) { + printf("HTM torture\n"); + printf(" -a : Run all workloads\n"); + printf(" -s : Run just a single workload\n"); + printf(" -l : List all workloads\n"); + printf(" -i : Run forever\n"); + printf(" -n : Amount of threads\n"); + printf(" -c : Only workloads that commit\n"); + printf(" -f : Only workloads that fails\n"); + printf(" -v : Be verbose\n"); + exit(1); + } + + if (debug) + printf("Thread per worload type: %d\n", nr_threads); + + do { + if (runworkload == ALL) { + printf("Starting all workloads\n"); + for (i = 0 ; i <= nr_workloads ; i++) + start_workers(i, nr_threads); + } else if (runworkload == FAIL) { + printf("Starting workloads which the transactions will fail\n"); + start_workers(0, nr_threads); + start_workers(1, nr_threads); + start_workers(3, nr_threads); + start_workers(6, nr_threads); + start_workers(8, nr_threads); + start_workers(9, nr_threads); + } else if (runworkload == NON_FAIL) { + printf("Starting workloads which the transactions will commit\n"); + start_workers(2, nr_threads); + start_workers(4, nr_threads); + start_workers(5, nr_threads); + start_workers(7, nr_threads); + start_workers(10, nr_threads); + } else { + start_workers(runworkload, nr_threads); + } + + join_workers(); + } while (infinityrun); + + printf("\nStatistics:\n"); + if (debug) { + printf("TM fails : %ld\n", tm_fails); + printf("TM commits: %ld\n", tm_commit); + } + + printf("Fail Percentage: %1.2f %% \n", + (float) 100*tm_fails/(tm_fails + tm_commit)); + + + return (0); +} Index: tools/tools/htm_torture/worker.c =================================================================== --- /dev/null +++ tools/tools/htm_torture/worker.c @@ -0,0 +1,560 @@ +/* + * Copyright (c) 2017 Breno Leitao, Gustavo Romero, IBM Corp. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "torture.h" +#include + +void *worker(void *arg) +{ + // I know you will frown upon void * to int cast ;-) + uint64_t workload = (int) arg; + + uint64_t nr; + uint64_t res; + // VSX registers. To be used in the future. + register vector __int128 vsx0 asm ("vs0") __attribute__((unused)); + register vector __int128 vsx1 asm ("vs1") __attribute__((unused)); + + // VMX registers. + register vector __int128 vmx0 asm ("vs32") __attribute__((unused)); + register vector __int128 vmx1 asm ("vs33") __attribute__((unused)); + register vector __int128 vmx2 asm ("vs34") __attribute__((unused)); + register vector __int128 vmx3 asm ("vs35") __attribute__((unused)); + register vector __int128 vmx4 asm ("vs36") __attribute__((unused)); + register vector __int128 vmx5 asm ("vs37") __attribute__((unused)); + register vector __int128 vmx6 asm ("vs38") __attribute__((unused)); + register vector __int128 vmx7 asm ("vs39") __attribute__((unused)); + register vector __int128 vmx8 asm ("vs40") __attribute__((unused)); + register vector __int128 vmx9 asm ("vs41") __attribute__((unused)); + register vector __int128 vmx10 asm ("vs42") __attribute__((unused)); + register vector __int128 vmx11 asm ("vs43") __attribute__((unused)); + register vector __int128 vmx12 asm ("vs44") __attribute__((unused)); + register vector __int128 vmx13 asm ("vs45") __attribute__((unused)); + register vector __int128 vmx14 asm ("vs46") __attribute__((unused)); + register vector __int128 vmx15 asm ("vs47") __attribute__((unused)); + register vector __int128 vmx16 asm ("vs48") __attribute__((unused)); + register vector __int128 vmx17 asm ("vs49") __attribute__((unused)); + register vector __int128 vmx18 asm ("vs50") __attribute__((unused)); + register vector __int128 vmx19 asm ("vs51") __attribute__((unused)); + register vector __int128 vmx20 asm ("vs52") __attribute__((unused)); + register vector __int128 vmx21 asm ("vs53") __attribute__((unused)); + register vector __int128 vmx22 asm ("vs54") __attribute__((unused)); + register vector __int128 vmx23 asm ("vs55") __attribute__((unused)); + register vector __int128 vmx24 asm ("vs56") __attribute__((unused)); + register vector __int128 vmx25 asm ("vs57") __attribute__((unused)); + register vector __int128 vmx26 asm ("vs58") __attribute__((unused)); + register vector __int128 vmx27 asm ("vs59") __attribute__((unused)); + register vector __int128 vmx28 asm ("vs60") __attribute__((unused)); + register vector __int128 vmx29 asm ("vs61") __attribute__((unused)); + register vector __int128 vmx30 asm ("vs62") __attribute__((unused)); + register vector __int128 vmx31 asm ("vs63") __attribute__((unused)); + + vector __int128 vmx_correct_value[32]; + vector __int128 vmx_scratch_area[2]; + + uint64_t offset = 0; + uint64_t z; + + if (debug) + printf("Thread executing workload %s: ", (char *) wname[workload]); + + // Expected correct values restored after a HTM failure. + vmx_correct_value[0] = (vector __int128) {0xBEEF}; + vmx_correct_value[1] = (vector __int128) {0xBEEF}; + vmx_correct_value[2] = (vector __int128) {0xBEEF}; + vmx_correct_value[3] = (vector __int128) {0xBEEF}; + vmx_correct_value[4] = (vector __int128) {0xBEEF}; + vmx_correct_value[5] = (vector __int128) {0xBEEF}; + vmx_correct_value[6] = (vector __int128) {0xBEEF}; + vmx_correct_value[7] = (vector __int128) {0xBEEF}; + vmx_correct_value[8] = (vector __int128) {0xBEEF}; + vmx_correct_value[9] = (vector __int128) {0xBEEF}; + vmx_correct_value[10] = (vector __int128) {0xBEEF}; + vmx_correct_value[11] = (vector __int128) {0xBEEF}; + vmx_correct_value[12] = (vector __int128) {0xBEEF}; + vmx_correct_value[13] = (vector __int128) {0xBEEF}; + vmx_correct_value[14] = (vector __int128) {0xBEEF}; + vmx_correct_value[15] = (vector __int128) {0xBEEF}; + vmx_correct_value[16] = (vector __int128) {0xBEEF}; + vmx_correct_value[17] = (vector __int128) {0xBEEF}; + vmx_correct_value[18] = (vector __int128) {0xBEEF}; + vmx_correct_value[19] = (vector __int128) {0xBEEF}; + vmx_correct_value[20] = (vector __int128) {0xBEEF}; + vmx_correct_value[21] = (vector __int128) {0xBEEF}; + vmx_correct_value[22] = (vector __int128) {0xBEEF}; + vmx_correct_value[23] = (vector __int128) {0xBEEF}; + vmx_correct_value[24] = (vector __int128) {0xBEEF}; + vmx_correct_value[25] = (vector __int128) {0xBEEF}; + vmx_correct_value[26] = (vector __int128) {0xBEEF}; + vmx_correct_value[27] = (vector __int128) {0xBEEF}; + vmx_correct_value[28] = (vector __int128) {0xBEEF}; + vmx_correct_value[29] = (vector __int128) {0xBEEF}; + vmx_correct_value[30] = (vector __int128) {0xBEEF}; + vmx_correct_value[31] = (vector __int128) {0xBEEF}; + + // Expected correct value restored to VRSAVE after a HTM failure. + // A place to keep the correct value in memory + uint64_t vrsave_correct_value[1]; + + // The correct value itself, a 32-bit value + vrsave_correct_value[0] = 0xBABEBEEF; + + // Set values for each VMX register just before entering in a + // transactional block. Values below must match the expected correct + // values after a HTM failure, as specified in the code section above. + + // TODO: add random generated value as the expected correct values to + // torture kernel VMX restore code. + + vmx0 = (vector __int128) {0xBEEF}; + vmx1 = (vector __int128) {0xBEEF}; + vmx2 = (vector __int128) {0xBEEF}; + vmx3 = (vector __int128) {0xBEEF}; + vmx4 = (vector __int128) {0xBEEF}; + vmx5 = (vector __int128) {0xBEEF}; + vmx6 = (vector __int128) {0xBEEF}; + vmx7 = (vector __int128) {0xBEEF}; + vmx8 = (vector __int128) {0xBEEF}; + vmx9 = (vector __int128) {0xBEEF}; + vmx10 = (vector __int128) {0xBEEF}; + vmx11 = (vector __int128) {0xBEEF}; + vmx12 = (vector __int128) {0xBEEF}; + vmx13 = (vector __int128) {0xBEEF}; + vmx14 = (vector __int128) {0xBEEF}; + vmx15 = (vector __int128) {0xBEEF}; + vmx16 = (vector __int128) {0xBEEF}; + vmx17 = (vector __int128) {0xBEEF}; + vmx18 = (vector __int128) {0xBEEF}; + vmx19 = (vector __int128) {0xBEEF}; + vmx20 = (vector __int128) {0xBEEF}; + vmx21 = (vector __int128) {0xBEEF}; + vmx22 = (vector __int128) {0xBEEF}; + vmx23 = (vector __int128) {0xBEEF}; + vmx24 = (vector __int128) {0xBEEF}; + vmx25 = (vector __int128) {0xBEEF}; + vmx26 = (vector __int128) {0xBEEF}; + vmx27 = (vector __int128) {0xBEEF}; + vmx28 = (vector __int128) {0xBEEF}; + vmx29 = (vector __int128) {0xBEEF}; + vmx30 = (vector __int128) {0xBEEF}; + vmx31 = (vector __int128) {0xBEEF}; + + // Set value for VRSAVE register just before entering in HTM block. + _ ("lwz 5, 0(%[vrsave_correct_value]) \n\t" + "mtvrsave 5 \n\t" + : + : [vrsave_correct_value] "r"(vrsave_correct_value) + : "r5" + ); + + /*************** + ** HTM BEGIN ** + ****************/ + _ ("tbegin. \n\t"); + _ goto ("beq %l[_failure] \n\t" : : : : _failure); + + /************** + ** HTM BODY ** + **************/ + + // Mess with the VRSAVE using a random value taken from Time Base + // register. + _ ("mftb 5 \n\t" + "mtvrsave 5 \n\t" + : + : + : "r5" + ); + + // We set VMX register with a value different from what they + // were set *before* entering the HTM. If the transaction + // fails, then VMX registers after _failure is taken must + // be restored back to the values *before* entering the HTM. + vmx0 = (vector __int128) {0xBABE}; + vmx1 = (vector __int128) {0xBABE}; + vmx2 = (vector __int128) {0xBABE}; + vmx3 = (vector __int128) {0xBABE}; + vmx4 = (vector __int128) {0xBABE}; + vmx5 = (vector __int128) {0xBABE}; + vmx6 = (vector __int128) {0xBABE}; + vmx7 = (vector __int128) {0xBABE}; + vmx8 = (vector __int128) {0xBABE}; + vmx9 = (vector __int128) {0xBABE}; + vmx10 = (vector __int128) {0xBABE}; + vmx11 = (vector __int128) {0xBABE}; + vmx12 = (vector __int128) {0xBABE}; + vmx13 = (vector __int128) {0xBABE}; + vmx14 = (vector __int128) {0xBABE}; + vmx15 = (vector __int128) {0xBABE}; + vmx16 = (vector __int128) {0xBABE}; + vmx17 = (vector __int128) {0xBABE}; + vmx18 = (vector __int128) {0xBABE}; + vmx19 = (vector __int128) {0xBABE}; + vmx20 = (vector __int128) {0xBABE}; + vmx21 = (vector __int128) {0xBABE}; + vmx22 = (vector __int128) {0xBABE}; + vmx23 = (vector __int128) {0xBABE}; + vmx24 = (vector __int128) {0xBABE}; + vmx25 = (vector __int128) {0xBABE}; + vmx26 = (vector __int128) {0xBABE}; + vmx27 = (vector __int128) {0xBABE}; + vmx28 = (vector __int128) {0xBABE}; + vmx29 = (vector __int128) {0xBABE}; + vmx30 = (vector __int128) {0xBABE}; + vmx31 = (vector __int128) {0xBABE}; + + // Call workload. + if (workloads[workload] == NULL) { + printf("ERROR: Workload %ld is NULL. Aborting\n", workload); + exit(-200); + } else + (*workloads[workload])(); + + /************* + ** HTM END ** + *************/ + _ ("tend. \n\t"); + _ goto ("b %l[_success] \n\t" : : : : _success); + + +_failure: + _ goto ( + + // Check if VRSAVE is sane. + "lwz 5, 0(%[vrsave_correct_value]) \n\t" + "mfvrsave 6 \n\t" + "cmpd 5, 6 \n\t" + "li 6, 32 \n\t" + "bne %l[_value_mismatch] \n\t" + + // Check if vmx0 is sane. + "stvx 1, 0, %[vmx_scratch_area] \n\t" + "lvx 1, 0, %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 1 \n\t" + "lvx 1, 0, %[vmx_scratch_area] \n\t" + "mfvrd 5, 0 \n\t" + "li 6, 0 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx1 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 1 \n\t" + "mfvrd 5, 1 \n\t" + "li 6, 1 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx2 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 2 \n\t" + "mfvrd 5, 2 \n\t" + "li 6, 2 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx3 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 3 \n\t" + "mfvrd 5, 3 \n\t" + "li 6, 3 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx4 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 4 \n\t" + "mfvrd 5, 4 \n\t" + "li 6, 4 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx5 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 5 \n\t" + "mfvrd 5, 5 \n\t" + "li 6, 5 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx6 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 6 \n\t" + "mfvrd 5, 6 \n\t" + "li 6, 6 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx7 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 7 \n\t" + "mfvrd 5, 7 \n\t" + "li 6, 7 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx8 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 8 \n\t" + "mfvrd 5, 8 \n\t" + "li 6, 8 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx9 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 9 \n\t" + "mfvrd 5, 9 \n\t" + "li 6, 9 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx10 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 10 \n\t" + "mfvrd 5, 10 \n\t" + "li 6, 10 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx11 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 11 \n\t" + "mfvrd 5, 11 \n\t" + "li 6, 11 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx12 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 12 \n\t" + "mfvrd 5, 12 \n\t" + "li 6, 12 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx13 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 13 \n\t" + "mfvrd 5, 13 \n\t" + "li 6, 13 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx14 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 14 \n\t" + "mfvrd 5, 14 \n\t" + "li 6, 14 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx15 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 15 \n\t" + "mfvrd 5, 15 \n\t" + "li 6, 15 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx16 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 16 \n\t" + "mfvrd 5, 16 \n\t" + "li 6, 16 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx17 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 17 \n\t" + "mfvrd 5, 17 \n\t" + "li 6, 17 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx18 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 18 \n\t" + "mfvrd 5, 18 \n\t" + "li 6, 18 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx19 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 19 \n\t" + "mfvrd 5, 19 \n\t" + "li 6, 19 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx20 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 20 \n\t" + "mfvrd 5, 20 \n\t" + "li 6, 20 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx21 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 21 \n\t" + "mfvrd 5, 21 \n\t" + "li 6, 21 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx22 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 22 \n\t" + "mfvrd 5, 22 \n\t" + "li 6, 22 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx23 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 23 \n\t" + "mfvrd 5, 23 \n\t" + "li 6, 23 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx24 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 24 \n\t" + "mfvrd 5, 24 \n\t" + "li 6, 24 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx25 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 25 \n\t" + "mfvrd 5, 25 \n\t" + "li 6, 25 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx26 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 26 \n\t" + "mfvrd 5, 26 \n\t" + "li 6, 26 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx27 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 27 \n\t" + "mfvrd 5, 27 \n\t" + "li 6, 27 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx28 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 28 \n\t" + "mfvrd 5, 28 \n\t" + "li 6, 28 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx29 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 29 \n\t" + "mfvrd 5, 29 \n\t" + "li 6, 29 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx30 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 30 \n\t" + "mfvrd 5, 30 \n\t" + "li 6, 30 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Check if vmx31 is sane. + "addi %[offset], %[offset], 16 \n\t" + "lvx 0, %[offset], %[vmx_correct_value] \n\t" + "vcmpequb. 0, 0, 31 \n\t" + "mfvrd 5, 31 \n\t" + "li 6, 31 \n\t" + "bc 4, 24, %l[_value_mismatch] \n\t" + + // Reach here, then all registers are sane. + "b %l[_value_match] \n\t" + + : // no output + : [offset] "r"(offset), + [vmx_correct_value] "r"(vmx_correct_value), + [vmx_scratch_area] "r"(vmx_scratch_area), + [vrsave_correct_value] "r"(vrsave_correct_value) + : "memory", "r5", "r6" + : _value_match, _value_mismatch + ); + +_value_mismatch: + z = __builtin_get_texasr(); + printf("\n\n==============\n\n"); + printf("\nFailure with error: %lx\n\n", _TEXASR_FAILURE_CODE(z)); + printf(": Summary error: %lx\n", _TEXASR_FAILURE_SUMMARY(z)); + printf(": TFIAR error: %lx\n", _TEXASR_TFIAR_EXACT(z)); + printf(": TEXASR: %.16lx\n", z); + printf(": Workload: %ld\n\n", workload); + + _ (".long 0"); // exit with a core dump + // TODO: move 'nr' and 'res' to input list in inline asm above and + // remove from here. + _ ("mr %[nr], 6 \n\t": [nr] "=r"(nr) : :); + _ ("mr %[res], 5 \n\t": [res] "=r"(res) : :); + + if (nr == 32) { // VRSAVE got corrupted + printf("Wordload %ld: register VRSAVE got corrupted.\n", workload); + printf("HTM failed and VRSAVE register got corrupted!\n"); + exit(13); + } else { // VSX/VMX got corrupted + printf("Workload %ld: register vs%"PRIu64 " contains value 0x%"PRIx64"\n", workload, nr+32, res); + printf("HTM failed and VMX registers got corrupted!\n"); + exit(14); + } + +_value_match: + printf("!"); + tm_fails++; + if (debug) + printf(" HTM failed but VMX and VRSAVE registers are OK\n"); + goto _finish; + +_success: + printf("."); + tm_commit++; + if (debug) + printf(" HTM succeeded\n"); +_finish: + + return 0; +} Index: tools/tools/htm_torture/workload.c =================================================================== --- /dev/null +++ tools/tools/htm_torture/workload.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2017 Breno Leitao, Gustavo Romero, IBM Corp. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "torture.h" + +unsigned long *array; +extern void QuickSort(unsigned long *a, int left, int right); + +/* Abort due to syscall (write); */ +void scall() +{ + printf("Workload 0\n"); +} + +/* Simple fibonnaci function */ +int fib(int x) +{ + if (x == 2 || x == 1) + return 1; + + return fib(x-1) + fib(x-2); +} + +/* Run a fibonnaci of 40 inside transaction */ +void fibonacci() { + int sum __attribute__((unused)); + int n = 40; + + sum = fib(n); +} + +/* single nop inside a transaction */ +void nop() { + _ ("or 0,0,0 \n"); +} + +/* Calling tabort inside transaction */ +void tabort() { + _ ("tabort. 0\n"); +} + +/* Quick sort workload */ +void quicksort(int *A, int len) +{ + int pivot = A[len / 2]; + int i, j; + int temp; + + if (len < 2) return; + + for (i = 0, j = len - 1; ; i++, j--) { + while (A[i] < pivot) i++; + while (A[j] > pivot) j--; + + if (i >= j) break; + + temp = A[i]; + A[i] = A[j]; + A[j] = temp; + } + + quicksort(A, i); + quicksort(A + i, len - i); +} + +/* Quicksort workload */ +void ownqsort() +{ + int a[] = {12, 3}; //, 9, 4, 9, 64}; + int n = sizeof a / sizeof a[0]; + quicksort(a, n); +} + +/* loop */ +void loop() +{ + int i ; + for (i=0; i < 10; ) + i++; +} + +// Infinite loop. +void iloop() +{ + while(1); +} + +/*** workdload7 ***/ +void utpsm_qsort() +{ + QuickSort(array, 0, ARRAY_SIZE-1); +} + +// illegal instruction. +void illegal() { + _ (".long 0x0"); +} + +// trap +void trap() +{ + _ ("trap"); +} + +void dscr() +{ + _ ("mfdscr 9"); + _ ("mtdscr 9"); +}