109 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * POWER Data Stream Control Register (DSCR) fork exec test4 *5 * This testcase modifies the DSCR using mtspr, forks & execs and6 * verifies that the child is using the changed DSCR using mfspr.7 *8 * When using the privilege state SPR, the instructions such as9 * mfspr or mtspr are privileged and the kernel emulates them10 * for us. Instructions using problem state SPR can be executed11 * directly without any emulation if the HW supports them. Else12 * 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 SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));48 49 for (i = 0; i < COUNT; i++) {50 dscr++;51 if (dscr > DSCR_MAX)52 dscr = 0;53 54 if (dscr == get_default_dscr())55 continue;56 57 if (i % 2 == 0)58 set_dscr_usr(dscr);59 else60 set_dscr(dscr);61 62 pid = fork();63 if (pid == -1) {64 perror("fork() failed");65 exit(1);66 } else if (pid) {67 int status;68 69 if (waitpid(pid, &status, 0) == -1) {70 perror("waitpid() failed");71 exit(1);72 }73 74 if (!WIFEXITED(status)) {75 fprintf(stderr, "Child didn't exit cleanly\n");76 exit(1);77 }78 79 if (WEXITSTATUS(status) != 0) {80 fprintf(stderr, "Child didn't exit cleanly\n");81 return 1;82 }83 } else {84 char dscr_str[16];85 86 sprintf(dscr_str, "%ld", dscr);87 execlp(prog, prog, "exec", dscr_str, NULL);88 exit(1);89 }90 }91 return 0;92}93 94int main(int argc, char *argv[])95{96 if (argc == 3 && !strcmp(argv[1], "exec")) {97 unsigned long parent_dscr;98 99 parent_dscr = atoi(argv[2]);100 do_exec(parent_dscr);101 } else if (argc != 1) {102 fprintf(stderr, "Usage: %s\n", argv[0]);103 exit(1);104 }105 106 prog = argv[0];107 return test_harness(dscr_inherit_exec, "dscr_inherit_exec_test");108}109