diff options
author | Linus Torvalds | 2019-05-10 05:29:27 -0700 |
---|---|---|
committer | Linus Torvalds | 2019-05-10 05:29:27 -0700 |
commit | b970afcfcabd63cd3832e95db096439c177c3592 (patch) | |
tree | b63e662c780e02617916f4c0269e2adddc67f5a0 /tools | |
parent | 8ea5b2abd07e2280a332bd9c1a7f4dd15b9b6c13 (diff) | |
parent | 8150a153c013aa2dd1ffae43370b89ac1347a7fb (diff) |
Merge tag 'powerpc-5.2-1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc updates from Michael Ellerman:
"Slightly delayed due to the issue with printk() calling
probe_kernel_read() interacting with our new user access prevention
stuff, but all fixed now.
The only out-of-area changes are the addition of a cpuhp_state, small
additions to Documentation and MAINTAINERS updates.
Highlights:
- Support for Kernel Userspace Access/Execution Prevention (like
SMAP/SMEP/PAN/PXN) on some 64-bit and 32-bit CPUs. This prevents
the kernel from accidentally accessing userspace outside
copy_to/from_user(), or ever executing userspace.
- KASAN support on 32-bit.
- Rework of where we map the kernel, vmalloc, etc. on 64-bit hash to
use the same address ranges we use with the Radix MMU.
- A rewrite into C of large parts of our idle handling code for
64-bit Book3S (ie. power8 & power9).
- A fast path entry for syscalls on 32-bit CPUs, for a 12-17% speedup
in the null_syscall benchmark.
- On 64-bit bare metal we have support for recovering from errors
with the time base (our clocksource), however if that fails
currently we hang in __delay() and never crash. We now have support
for detecting that case and short circuiting __delay() so we at
least panic() and reboot.
- Add support for optionally enabling the DAWR on Power9, which had
to be disabled by default due to a hardware erratum. This has the
effect of enabling hardware breakpoints for GDB, the downside is a
badly behaved program could crash the machine by pointing the DAWR
at cache inhibited memory. This is opt-in obviously.
- xmon, our crash handler, gets support for a read only mode where
operations that could change memory or otherwise disturb the system
are disabled.
Plus many clean-ups, reworks and minor fixes etc.
Thanks to: Christophe Leroy, Akshay Adiga, Alastair D'Silva, Alexey
Kardashevskiy, Andrew Donnellan, Aneesh Kumar K.V, Anju T Sudhakar,
Anton Blanchard, Ben Hutchings, Bo YU, Breno Leitao, Cédric Le Goater,
Christopher M. Riedl, Christoph Hellwig, Colin Ian King, David Gibson,
Ganesh Goudar, Gautham R. Shenoy, George Spelvin, Greg Kroah-Hartman,
Greg Kurz, Horia Geantă, Jagadeesh Pagadala, Joel Stanley, Joe
Perches, Julia Lawall, Laurentiu Tudor, Laurent Vivier, Lukas Bulwahn,
Madhavan Srinivasan, Mahesh Salgaonkar, Mathieu Malaterre, Michael
Neuling, Mukesh Ojha, Nathan Fontenot, Nathan Lynch, Nicholas Piggin,
Nick Desaulniers, Oliver O'Halloran, Peng Hao, Qian Cai, Ravi
Bangoria, Rick Lindsley, Russell Currey, Sachin Sant, Stewart Smith,
Sukadev Bhattiprolu, Thomas Huth, Tobin C. Harding, Tyrel Datwyler,
Valentin Schneider, Wei Yongjun, Wen Yang, YueHaibing"
* tag 'powerpc-5.2-1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (205 commits)
powerpc/64s: Use early_mmu_has_feature() in set_kuap()
powerpc/book3s/64: check for NULL pointer in pgd_alloc()
powerpc/mm: Fix hugetlb page initialization
ocxl: Fix return value check in afu_ioctl()
powerpc/mm: fix section mismatch for setup_kup()
powerpc/mm: fix redundant inclusion of pgtable-frag.o in Makefile
powerpc/mm: Fix makefile for KASAN
powerpc/kasan: add missing/lost Makefile
selftests/powerpc: Add a signal fuzzer selftest
powerpc/booke64: set RI in default MSR
ocxl: Provide global MMIO accessors for external drivers
ocxl: move event_fd handling to frontend
ocxl: afu_irq only deals with IRQ IDs, not offsets
ocxl: Allow external drivers to use OpenCAPI contexts
ocxl: Create a clear delineation between ocxl backend & frontend
ocxl: Don't pass pci_dev around
ocxl: Split pci.c
ocxl: Remove some unused exported symbols
ocxl: Remove superfluous 'extern' from headers
ocxl: read_pasid never returns an error, so make it void
...
Diffstat (limited to 'tools')
-rw-r--r-- | tools/testing/selftests/powerpc/copyloops/asm/export.h | 1 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/copyloops/asm/kasan.h | 0 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h | 1 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/harness.c | 6 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/include/reg.h | 2 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/signal/.gitignore | 1 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/signal/Makefile | 3 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/signal/sigfuz.c | 325 | ||||
l--------- | tools/testing/selftests/powerpc/vphn/vphn.c | 2 | ||||
l--------- | tools/testing/selftests/powerpc/vphn/vphn.h | 2 |
10 files changed, 338 insertions, 5 deletions
diff --git a/tools/testing/selftests/powerpc/copyloops/asm/export.h b/tools/testing/selftests/powerpc/copyloops/asm/export.h index 0bab35f6777a..05c1663c89b0 100644 --- a/tools/testing/selftests/powerpc/copyloops/asm/export.h +++ b/tools/testing/selftests/powerpc/copyloops/asm/export.h @@ -1,2 +1,3 @@ /* SPDX-License-Identifier: GPL-2.0 */ #define EXPORT_SYMBOL(x) +#define EXPORT_SYMBOL_KASAN(x) diff --git a/tools/testing/selftests/powerpc/copyloops/asm/kasan.h b/tools/testing/selftests/powerpc/copyloops/asm/kasan.h new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/tools/testing/selftests/powerpc/copyloops/asm/kasan.h diff --git a/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h b/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h index 0605df807593..58c1cef3e399 100644 --- a/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h +++ b/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h @@ -25,6 +25,7 @@ #define _GLOBAL(A) FUNC_START(test_ ## A) #define _GLOBAL_TOC(A) _GLOBAL(A) +#define _GLOBAL_TOC_KASAN(A) _GLOBAL(A) #define PPC_MTOCRF(A, B) mtocrf A, B diff --git a/tools/testing/selftests/powerpc/harness.c b/tools/testing/selftests/powerpc/harness.c index 9d7166dfad1e..ba89353abfcc 100644 --- a/tools/testing/selftests/powerpc/harness.c +++ b/tools/testing/selftests/powerpc/harness.c @@ -21,6 +21,7 @@ #define KILL_TIMEOUT 5 +/* Setting timeout to -1 disables the alarm */ static uint64_t timeout = 120; int run_test(int (test_function)(void), char *name) @@ -43,8 +44,9 @@ int run_test(int (test_function)(void), char *name) setpgid(pid, pid); - /* Wake us up in timeout seconds */ - alarm(timeout); + if (timeout != -1) + /* Wake us up in timeout seconds */ + alarm(timeout); terminated = false; wait: diff --git a/tools/testing/selftests/powerpc/include/reg.h b/tools/testing/selftests/powerpc/include/reg.h index 96043b9b9829..1e797ae396ee 100644 --- a/tools/testing/selftests/powerpc/include/reg.h +++ b/tools/testing/selftests/powerpc/include/reg.h @@ -79,11 +79,13 @@ /* MSR register bits */ #define MSR_TS_S_LG 33 /* Trans Mem state: Suspended */ +#define MSR_TS_T_LG 34 /* Trans Mem state: Active */ #define __MASK(X) (1UL<<(X)) /* macro to check TM MSR bits */ #define MSR_TS_S __MASK(MSR_TS_S_LG) /* Transaction Suspended */ +#define MSR_TS_T __MASK(MSR_TS_T_LG) /* Transaction Transactional */ /* Vector Instructions */ #define VSX_XX1(xs, ra, rb) (((xs) & 0x1f) << 21 | ((ra) << 16) | \ diff --git a/tools/testing/selftests/powerpc/signal/.gitignore b/tools/testing/selftests/powerpc/signal/.gitignore index 1b89224a8aab..dca5852a1546 100644 --- a/tools/testing/selftests/powerpc/signal/.gitignore +++ b/tools/testing/selftests/powerpc/signal/.gitignore @@ -1,2 +1,3 @@ signal signal_tm +sigfuz diff --git a/tools/testing/selftests/powerpc/signal/Makefile b/tools/testing/selftests/powerpc/signal/Makefile index 209a958dca12..113838fbbe7f 100644 --- a/tools/testing/selftests/powerpc/signal/Makefile +++ b/tools/testing/selftests/powerpc/signal/Makefile @@ -1,8 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 -TEST_GEN_PROGS := signal signal_tm +TEST_GEN_PROGS := signal signal_tm sigfuz CFLAGS += -maltivec $(OUTPUT)/signal_tm: CFLAGS += -mhtm +$(OUTPUT)/sigfuz: CFLAGS += -pthread -m64 top_srcdir = ../../../../.. include ../../lib.mk diff --git a/tools/testing/selftests/powerpc/signal/sigfuz.c b/tools/testing/selftests/powerpc/signal/sigfuz.c new file mode 100644 index 000000000000..dade00c698c2 --- /dev/null +++ b/tools/testing/selftests/powerpc/signal/sigfuz.c @@ -0,0 +1,325 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2018, Breno Leitao, IBM Corp. + * Licensed under GPLv2. + * + * Sigfuz(tm): A PowerPC TM-aware signal fuzzer. + * + * This is a new selftest that raises SIGUSR1 signals and handles it in a set + * of different ways, trying to create different scenario for testing + * purpose. + * + * This test works raising a signal and calling sigreturn interleaved with + * TM operations, as starting, suspending and terminating a transaction. The + * test depends on random numbers, and, based on them, it sets different TM + * states. + * + * Other than that, the test fills out the user context struct that is passed + * to the sigreturn system call with random data, in order to make sure that + * the signal handler syscall can handle different and invalid states + * properly. + * + * This selftest has command line parameters to control what kind of tests the + * user wants to run, as for example, if a transaction should be started prior + * to signal being raised, or, after the signal being raised and before the + * sigreturn. If no parameter is given, the default is enabling all options. + * + * This test does not check if the user context is being read and set + * properly by the kernel. Its purpose, at this time, is basically + * guaranteeing that the kernel does not crash on invalid scenarios. + */ + +#include <stdio.h> +#include <limits.h> +#include <sys/wait.h> +#include <unistd.h> +#include <stdlib.h> +#include <signal.h> +#include <string.h> +#include <ucontext.h> +#include <sys/mman.h> +#include <pthread.h> +#include "utils.h" + +/* Selftest defaults */ +#define COUNT_MAX 4000 /* Number of interactions */ +#define THREADS 16 /* Number of threads */ + +/* Arguments options */ +#define ARG_MESS_WITH_TM_AT 0x1 +#define ARG_MESS_WITH_TM_BEFORE 0x2 +#define ARG_MESS_WITH_MSR_AT 0x4 +#define ARG_FOREVER 0x10 +#define ARG_COMPLETE (ARG_MESS_WITH_TM_AT | \ + ARG_MESS_WITH_TM_BEFORE | \ + ARG_MESS_WITH_MSR_AT) + +static int args; +static int nthread = THREADS; +static int count_max = COUNT_MAX; + +/* checkpoint context */ +static ucontext_t *tmp_uc; + +/* Return true with 1/x probability */ +static int one_in_chance(int x) +{ + return rand() % x == 0; +} + +/* Change TM states */ +static void mess_with_tm(void) +{ + /* Starts a transaction 33% of the time */ + if (one_in_chance(3)) { + asm ("tbegin. ;" + "beq 8 ;"); + + /* And suspended half of them */ + if (one_in_chance(2)) + asm("tsuspend. ;"); + } + + /* Call 'tend' in 5% of the runs */ + if (one_in_chance(20)) + asm("tend. ;"); +} + +/* Signal handler that will be invoked with raise() */ +static void trap_signal_handler(int signo, siginfo_t *si, void *uc) +{ + ucontext_t *ucp = uc; + + ucp->uc_link = tmp_uc; + + /* + * Set uc_link in three possible ways: + * - Setting a single 'int' in the whole chunk + * - Cloning ucp into uc_link + * - Allocating a new memory chunk + */ + if (one_in_chance(3)) { + memset(ucp->uc_link, rand(), sizeof(ucontext_t)); + } else if (one_in_chance(2)) { + memcpy(ucp->uc_link, uc, sizeof(ucontext_t)); + } else if (one_in_chance(2)) { + if (tmp_uc) { + free(tmp_uc); + tmp_uc = NULL; + } + tmp_uc = malloc(sizeof(ucontext_t)); + ucp->uc_link = tmp_uc; + /* Trying to cause a major page fault at Kernel level */ + madvise(ucp->uc_link, sizeof(ucontext_t), MADV_DONTNEED); + } + + if (args & ARG_MESS_WITH_MSR_AT) { + /* Changing the checkpointed registers */ + if (one_in_chance(4)) { + ucp->uc_link->uc_mcontext.gp_regs[PT_MSR] |= MSR_TS_S; + } else { + if (one_in_chance(2)) { + ucp->uc_link->uc_mcontext.gp_regs[PT_MSR] |= + MSR_TS_T; + } else if (one_in_chance(2)) { + ucp->uc_link->uc_mcontext.gp_regs[PT_MSR] |= + MSR_TS_T | MSR_TS_S; + } + } + + /* Checking the current register context */ + if (one_in_chance(2)) { + ucp->uc_mcontext.gp_regs[PT_MSR] |= MSR_TS_S; + } else if (one_in_chance(2)) { + if (one_in_chance(2)) + ucp->uc_mcontext.gp_regs[PT_MSR] |= + MSR_TS_T; + else if (one_in_chance(2)) + ucp->uc_mcontext.gp_regs[PT_MSR] |= + MSR_TS_T | MSR_TS_S; + } + } + + if (one_in_chance(20)) { + /* Nested transaction start */ + if (one_in_chance(5)) + mess_with_tm(); + + /* Return without changing any other context info */ + return; + } + + if (one_in_chance(10)) + ucp->uc_mcontext.gp_regs[PT_MSR] = random(); + if (one_in_chance(10)) + ucp->uc_mcontext.gp_regs[PT_NIP] = random(); + if (one_in_chance(10)) + ucp->uc_link->uc_mcontext.gp_regs[PT_MSR] = random(); + if (one_in_chance(10)) + ucp->uc_link->uc_mcontext.gp_regs[PT_NIP] = random(); + + ucp->uc_mcontext.gp_regs[PT_TRAP] = random(); + ucp->uc_mcontext.gp_regs[PT_DSISR] = random(); + ucp->uc_mcontext.gp_regs[PT_DAR] = random(); + ucp->uc_mcontext.gp_regs[PT_ORIG_R3] = random(); + ucp->uc_mcontext.gp_regs[PT_XER] = random(); + ucp->uc_mcontext.gp_regs[PT_RESULT] = random(); + ucp->uc_mcontext.gp_regs[PT_SOFTE] = random(); + ucp->uc_mcontext.gp_regs[PT_DSCR] = random(); + ucp->uc_mcontext.gp_regs[PT_CTR] = random(); + ucp->uc_mcontext.gp_regs[PT_LNK] = random(); + ucp->uc_mcontext.gp_regs[PT_CCR] = random(); + ucp->uc_mcontext.gp_regs[PT_REGS_COUNT] = random(); + + ucp->uc_link->uc_mcontext.gp_regs[PT_TRAP] = random(); + ucp->uc_link->uc_mcontext.gp_regs[PT_DSISR] = random(); + ucp->uc_link->uc_mcontext.gp_regs[PT_DAR] = random(); + ucp->uc_link->uc_mcontext.gp_regs[PT_ORIG_R3] = random(); + ucp->uc_link->uc_mcontext.gp_regs[PT_XER] = random(); + ucp->uc_link->uc_mcontext.gp_regs[PT_RESULT] = random(); + ucp->uc_link->uc_mcontext.gp_regs[PT_SOFTE] = random(); + ucp->uc_link->uc_mcontext.gp_regs[PT_DSCR] = random(); + ucp->uc_link->uc_mcontext.gp_regs[PT_CTR] = random(); + ucp->uc_link->uc_mcontext.gp_regs[PT_LNK] = random(); + ucp->uc_link->uc_mcontext.gp_regs[PT_CCR] = random(); + ucp->uc_link->uc_mcontext.gp_regs[PT_REGS_COUNT] = random(); + + if (args & ARG_MESS_WITH_TM_BEFORE) { + if (one_in_chance(2)) + mess_with_tm(); + } +} + +static void seg_signal_handler(int signo, siginfo_t *si, void *uc) +{ + /* Clear exit for process that segfaults */ + exit(0); +} + +static void *sigfuz_test(void *thrid) +{ + struct sigaction trap_sa, seg_sa; + int ret, i = 0; + pid_t t; + + tmp_uc = malloc(sizeof(ucontext_t)); + + /* Main signal handler */ + trap_sa.sa_flags = SA_SIGINFO; + trap_sa.sa_sigaction = trap_signal_handler; + + /* SIGSEGV signal handler */ + seg_sa.sa_flags = SA_SIGINFO; + seg_sa.sa_sigaction = seg_signal_handler; + + /* The signal handler will enable MSR_TS */ + sigaction(SIGUSR1, &trap_sa, NULL); + + /* If it does not crash, it will segfault, avoid it to retest */ + sigaction(SIGSEGV, &seg_sa, NULL); + + while (i < count_max) { + t = fork(); + + if (t == 0) { + /* Once seed per process */ + srand(time(NULL) + getpid()); + if (args & ARG_MESS_WITH_TM_AT) { + if (one_in_chance(2)) + mess_with_tm(); + } + raise(SIGUSR1); + exit(0); + } else { + waitpid(t, &ret, 0); + } + if (!(args & ARG_FOREVER)) + i++; + } + + /* If not freed already, free now */ + if (tmp_uc) { + free(tmp_uc); + tmp_uc = NULL; + } + + return NULL; +} + +static int signal_fuzzer(void) +{ + int t, rc; + pthread_t *threads; + + threads = malloc(nthread * sizeof(pthread_t)); + + for (t = 0; t < nthread; t++) { + rc = pthread_create(&threads[t], NULL, sigfuz_test, + (void *)&t); + if (rc) + perror("Thread creation error\n"); + } + + for (t = 0; t < nthread; t++) { + rc = pthread_join(threads[t], NULL); + if (rc) + perror("Thread join error\n"); + } + + free(threads); + + return EXIT_SUCCESS; +} + +static void show_help(char *name) +{ + printf("%s: Sigfuzzer for powerpc\n", name); + printf("Usage:\n"); + printf("\t-b\t Mess with TM before raising a SIGUSR1 signal\n"); + printf("\t-a\t Mess with TM after raising a SIGUSR1 signal\n"); + printf("\t-m\t Mess with MSR[TS] bits at mcontext\n"); + printf("\t-x\t Mess with everything above\n"); + printf("\t-f\t Run forever (Press ^C to Quit)\n"); + printf("\t-i\t Amount of interactions. (Default = %d)\n", COUNT_MAX); + printf("\t-t\t Amount of threads. (Default = %d)\n", THREADS); + exit(-1); +} + +int main(int argc, char **argv) +{ + int opt; + + while ((opt = getopt(argc, argv, "bamxt:fi:h")) != -1) { + if (opt == 'b') { + printf("Mess with TM before signal\n"); + args |= ARG_MESS_WITH_TM_BEFORE; + } else if (opt == 'a') { + printf("Mess with TM at signal handler\n"); + args |= ARG_MESS_WITH_TM_AT; + } else if (opt == 'm') { + printf("Mess with MSR[TS] bits in mcontext\n"); + args |= ARG_MESS_WITH_MSR_AT; + } else if (opt == 'x') { + printf("Running with all options enabled\n"); + args |= ARG_COMPLETE; + } else if (opt == 't') { + nthread = atoi(optarg); + printf("Threads = %d\n", nthread); + } else if (opt == 'f') { + args |= ARG_FOREVER; + printf("Press ^C to stop\n"); + test_harness_set_timeout(-1); + } else if (opt == 'i') { + count_max = atoi(optarg); + printf("Running for %d interactions\n", count_max); + } else if (opt == 'h') { + show_help(argv[0]); + } + } + + /* Default test suite */ + if (!args) + args = ARG_COMPLETE; + + test_harness(signal_fuzzer, "signal_fuzzer"); +} diff --git a/tools/testing/selftests/powerpc/vphn/vphn.c b/tools/testing/selftests/powerpc/vphn/vphn.c index 186b906e66d5..1d1f5f2be3b2 120000 --- a/tools/testing/selftests/powerpc/vphn/vphn.c +++ b/tools/testing/selftests/powerpc/vphn/vphn.c @@ -1 +1 @@ -../../../../../arch/powerpc/mm/vphn.c
\ No newline at end of file +../../../../../arch/powerpc/mm/book3s64/vphn.c
\ No newline at end of file diff --git a/tools/testing/selftests/powerpc/vphn/vphn.h b/tools/testing/selftests/powerpc/vphn/vphn.h index 7131efe38c65..45fe160f8288 120000 --- a/tools/testing/selftests/powerpc/vphn/vphn.h +++ b/tools/testing/selftests/powerpc/vphn/vphn.h @@ -1 +1 @@ -../../../../../arch/powerpc/mm/vphn.h
\ No newline at end of file +../../../../../arch/powerpc/mm/book3s64/vphn.h
\ No newline at end of file |