On Mon, 2 May 2016 13:51:38 +1000
Chris Smart <ch...@distroguy.com> wrote:

> Test that performing a copy paste sequence in userspace on P9 does not
> result in a leak of the copy into the paste of another process.
> 
> This is based on Anton Blanchard's context_switch benchmarking code. It
> sets up two processes tied to the same CPU, one which copies and one
> which pastes.
> 
> The paste should never succeed and the test fails if it does.
> 
> This is a test for commit, "8a64904 powerpc: Add support for userspace
> P9 copy paste."
> 

Hi Chris,

I must admit I didn't run on it on real hardware ;).

Looks good.

> Patch created with much assistance from Michael Neuling
> <mi...@neuling.org>
> 
> Signed-off-by: Chris Smart <ch...@distroguy.com>

Reviewed-by: Cyril Bur <cyril...@gmail.com>

> ---
>  tools/testing/selftests/powerpc/Makefile           |   1 +
>  .../selftests/powerpc/context_switch/.gitignore    |   1 +
>  .../selftests/powerpc/context_switch/Makefile      |  10 ++
>  .../selftests/powerpc/context_switch/cp_abort.c    | 110 
> +++++++++++++++++++++
>  tools/testing/selftests/powerpc/utils.h            |   7 ++
>  5 files changed, 129 insertions(+)
>  create mode 100644 tools/testing/selftests/powerpc/context_switch/.gitignore
>  create mode 100644 tools/testing/selftests/powerpc/context_switch/Makefile
>  create mode 100644 tools/testing/selftests/powerpc/context_switch/cp_abort.c
> 
> diff --git a/tools/testing/selftests/powerpc/Makefile 
> b/tools/testing/selftests/powerpc/Makefile
> index b08f77cbe31b..4ca83fe80654 100644
> --- a/tools/testing/selftests/powerpc/Makefile
> +++ b/tools/testing/selftests/powerpc/Makefile
> @@ -14,6 +14,7 @@ export CFLAGS
>  
>  SUB_DIRS = benchmarks                \
>          copyloops            \
> +        context_switch       \
>          dscr                 \
>          mm                   \
>          pmu                  \
> diff --git a/tools/testing/selftests/powerpc/context_switch/.gitignore 
> b/tools/testing/selftests/powerpc/context_switch/.gitignore
> new file mode 100644
> index 000000000000..c1431af7b51c
> --- /dev/null
> +++ b/tools/testing/selftests/powerpc/context_switch/.gitignore
> @@ -0,0 +1 @@
> +cp_abort
> diff --git a/tools/testing/selftests/powerpc/context_switch/Makefile 
> b/tools/testing/selftests/powerpc/context_switch/Makefile
> new file mode 100644
> index 000000000000..e164d1466466
> --- /dev/null
> +++ b/tools/testing/selftests/powerpc/context_switch/Makefile
> @@ -0,0 +1,10 @@
> +TEST_PROGS := cp_abort
> +
> +all: $(TEST_PROGS)
> +
> +$(TEST_PROGS): ../harness.c ../utils.c
> +
> +include ../../lib.mk
> +
> +clean:
> +     rm -f $(TEST_PROGS)
> diff --git a/tools/testing/selftests/powerpc/context_switch/cp_abort.c 
> b/tools/testing/selftests/powerpc/context_switch/cp_abort.c
> new file mode 100644
> index 000000000000..5a5b55afda0e
> --- /dev/null
> +++ b/tools/testing/selftests/powerpc/context_switch/cp_abort.c
> @@ -0,0 +1,110 @@
> +/*
> + * Adapted from Anton Blanchard's context switch microbenchmark.
> + *
> + * Copyright 2009, Anton Blanchard, IBM Corporation.
> + * Copyright 2016, Mikey Neuling, Chris Smart, IBM Corporation.
> + *
> + * 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.
> + *
> + * This program tests the copy paste abort functionality of a P9
> + * (or later) by setting up two processes on the same CPU, one
> + * which executes the copy instruction and the other which
> + * executes paste.
> + *
> + * The paste instruction should never succeed, as the cp_abort
> + * instruction is called by the kernel during a context switch.
> + *
> + */
> +
> +#define _GNU_SOURCE
> +
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include "utils.h"
> +#include <sched.h>
> +
> +#define READ_FD 0
> +#define WRITE_FD 1
> +
> +#define NUM_LOOPS 1000
> +
> +/* This defines the "paste" instruction from Power ISA 3.0 Book II, section 
> 4.4. */
> +#define PASTE(RA, RB, L, RC) \
> +     .long (0x7c00070c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10) 
> | (RC) << (31-31))
> +
> +int paste(void *i)
> +{
> +     int cr;
> +
> +     asm volatile(str(PASTE(0, %1, 1, 1))";"
> +                     "mfcr %0;"
> +                     : "=r" (cr)
> +                     : "b" (i)
> +                     : "memory"
> +                 );
> +     return cr;
> +}
> +
> +/* This defines the "copy" instruction from Power ISA 3.0 Book II, section 
> 4.4. */
> +#define COPY(RA, RB, L) \
> +     .long (0x7c00060c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10))
> +
> +void copy(void *i)
> +{
> +     asm volatile(str(COPY(0, %0, 1))";"
> +                     :
> +                     : "b" (i)
> +                     : "memory"
> +                 );
> +}
> +
> +int test_cp_abort(void)
> +{
> +     /* 128 bytes for a full cache line */
> +     char buf[128] __cacheline_aligned;
> +     cpu_set_t cpuset;
> +     int fd1[2], fd2[2], pid;
> +     char c;
> +
> +     /* only run this test on a P9 or later */
> +     SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00));
> +
> +     /*
> +      * Run both processes on the same CPU, so that copy is more likely
> +      * to leak into a paste.
> +      */
> +     CPU_ZERO(&cpuset);
> +     CPU_SET(pick_online_cpu(), &cpuset);
> +     FAIL_IF(sched_setaffinity(0, sizeof(cpuset), &cpuset));
> +
> +     FAIL_IF(pipe(fd1) || pipe(fd2));
> +
> +     pid = fork();
> +     FAIL_IF(pid < 0);
> +
> +     if (!pid) {
> +             for (int i = 0; i < NUM_LOOPS; i++) {
> +                     FAIL_IF((write(fd1[WRITE_FD], &c, 1)) != 1);
> +                     FAIL_IF((read(fd2[READ_FD], &c, 1)) != 1);
> +                     /* A paste succeeds if CR0 EQ bit is set */
> +                     FAIL_IF(paste(buf) & 0x20000000);
> +             }
> +     } else {
> +             for (int i = 0; i < NUM_LOOPS; i++) {
> +                     FAIL_IF((read(fd1[READ_FD], &c, 1)) != 1);
> +                     copy(buf);
> +                     FAIL_IF((write(fd2[WRITE_FD], &c, 1) != 1));
> +             }
> +     }
> +     return 0;
> +
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +     return test_harness(test_cp_abort, "cp_abort");
> +}
> diff --git a/tools/testing/selftests/powerpc/utils.h 
> b/tools/testing/selftests/powerpc/utils.h
> index 175ac6ad10dd..3b370deafb62 100644
> --- a/tools/testing/selftests/powerpc/utils.h
> +++ b/tools/testing/selftests/powerpc/utils.h
> @@ -6,6 +6,8 @@
>  #ifndef _SELFTESTS_POWERPC_UTILS_H
>  #define _SELFTESTS_POWERPC_UTILS_H
>  
> +#define __cacheline_aligned __attribute__((aligned(128)))
> +
>  #include <stdint.h>
>  #include <stdbool.h>
>  #include <linux/auxvec.h>
> @@ -54,4 +56,9 @@ do {                                                        
>         \
>  #define _str(s) #s
>  #define str(s) _str(s)
>  
> +/* POWER9 feature */
> +#ifndef PPC_FEATURE2_ARCH_3_00
> +#define PPC_FEATURE2_ARCH_3_00 0x00800000
> +#endif
> +
>  #endif /* _SELFTESTS_POWERPC_UTILS_H */

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to