linux/tools/testing/selftests/powerpc/dscr/dscr_inherit_exec_test.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * POWER Data Stream Control Register (DSCR) fork exec test
   4 *
   5 * This testcase modifies the DSCR using mtspr, forks & execs and
   6 * verifies that the child is using the changed DSCR using mfspr.
   7 *
   8 * When using the privilege state SPR, the instructions such as
   9 * mfspr or mtspr are privileged and the kernel emulates them
  10 * for us. Instructions using problem state SPR can be executed
  11 * directly without any emulation if the HW supports them. Else
  12 * they also get emulated by the kernel.
  13 *
  14 * Copyright 2012, Anton Blanchard, IBM Corporation.
  15 * Copyright 2015, Anshuman Khandual, IBM Corporation.
  16 */
  17#include "dscr.h"
  18
  19static char *prog;
  20
  21static void do_exec(unsigned long parent_dscr)
  22{
  23        unsigned long cur_dscr, cur_dscr_usr;
  24
  25        cur_dscr = get_dscr();
  26        cur_dscr_usr = get_dscr_usr();
  27
  28        if (cur_dscr != parent_dscr) {
  29                fprintf(stderr, "Parent DSCR %ld was not inherited "
  30                                "over exec (kernel value)\n", parent_dscr);
  31                exit(1);
  32        }
  33
  34        if (cur_dscr_usr != parent_dscr) {
  35                fprintf(stderr, "Parent DSCR %ld was not inherited "
  36                                "over exec (user value)\n", parent_dscr);
  37                exit(1);
  38        }
  39        exit(0);
  40}
  41
  42int dscr_inherit_exec(void)
  43{
  44        unsigned long i, dscr = 0;
  45        pid_t pid;
  46
  47        for (i = 0; i < COUNT; i++) {
  48                dscr++;
  49                if (dscr > DSCR_MAX)
  50                        dscr = 0;
  51
  52                if (dscr == get_default_dscr())
  53                        continue;
  54
  55                if (i % 2 == 0)
  56                        set_dscr_usr(dscr);
  57                else
  58                        set_dscr(dscr);
  59
  60                pid = fork();
  61                if (pid == -1) {
  62                        perror("fork() failed");
  63                        exit(1);
  64                } else if (pid) {
  65                        int status;
  66
  67                        if (waitpid(pid, &status, 0) == -1) {
  68                                perror("waitpid() failed");
  69                                exit(1);
  70                        }
  71
  72                        if (!WIFEXITED(status)) {
  73                                fprintf(stderr, "Child didn't exit cleanly\n");
  74                                exit(1);
  75                        }
  76
  77                        if (WEXITSTATUS(status) != 0) {
  78                                fprintf(stderr, "Child didn't exit cleanly\n");
  79                                return 1;
  80                        }
  81                } else {
  82                        char dscr_str[16];
  83
  84                        sprintf(dscr_str, "%ld", dscr);
  85                        execlp(prog, prog, "exec", dscr_str, NULL);
  86                        exit(1);
  87                }
  88        }
  89        return 0;
  90}
  91
  92int main(int argc, char *argv[])
  93{
  94        if (argc == 3 && !strcmp(argv[1], "exec")) {
  95                unsigned long parent_dscr;
  96
  97                parent_dscr = atoi(argv[2]);
  98                do_exec(parent_dscr);
  99        } else if (argc != 1) {
 100                fprintf(stderr, "Usage: %s\n", argv[0]);
 101                exit(1);
 102        }
 103
 104        prog = argv[0];
 105        return test_harness(dscr_inherit_exec, "dscr_inherit_exec_test");
 106}
 107