Commit | Line | Data |
---|---|---|
3752e453 ME |
1 | /* |
2 | * Copyright 2014, Michael Ellerman, IBM Corp. | |
3 | * Licensed under GPLv2. | |
4 | */ | |
5 | ||
6 | #include <signal.h> | |
7 | #include <stdio.h> | |
8 | #include <stdlib.h> | |
9 | #include <stdbool.h> | |
10 | #include <sys/types.h> | |
11 | #include <sys/wait.h> | |
12 | #include <unistd.h> | |
13 | #include <setjmp.h> | |
3752e453 ME |
14 | |
15 | #include "ebb.h" | |
16 | ||
17 | ||
18 | /* | |
19 | * Test that a fork clears the PMU state of the child. eg. BESCR/EBBHR/EBBRR | |
20 | * are cleared, and MMCR0_PMCC is reset, preventing the child from accessing | |
21 | * the PMU. | |
22 | */ | |
23 | ||
24 | static struct event event; | |
25 | ||
26 | static int child(void) | |
27 | { | |
28 | /* Even though we have EBE=0 we can still see the EBB regs */ | |
29 | FAIL_IF(mfspr(SPRN_BESCR) != 0); | |
30 | FAIL_IF(mfspr(SPRN_EBBHR) != 0); | |
31 | FAIL_IF(mfspr(SPRN_EBBRR) != 0); | |
32 | ||
33 | FAIL_IF(catch_sigill(write_pmc1)); | |
34 | ||
35 | /* We can still read from the event, though it is on our parent */ | |
36 | FAIL_IF(event_read(&event)); | |
37 | ||
38 | return 0; | |
39 | } | |
40 | ||
41 | /* Tests that fork clears EBB state */ | |
42 | int fork_cleanup(void) | |
43 | { | |
44 | pid_t pid; | |
45 | ||
39fcfb91 DK |
46 | SKIP_IF(!ebb_is_supported()); |
47 | ||
3752e453 ME |
48 | event_init_named(&event, 0x1001e, "cycles"); |
49 | event_leader_ebb_init(&event); | |
50 | ||
51 | FAIL_IF(event_open(&event)); | |
52 | ||
53 | ebb_enable_pmc_counting(1); | |
54 | setup_ebb_handler(standard_ebb_callee); | |
55 | ebb_global_enable(); | |
56 | ||
57 | FAIL_IF(ebb_event_enable(&event)); | |
58 | ||
59 | mtspr(SPRN_MMCR0, MMCR0_FC); | |
60 | mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); | |
61 | ||
62 | /* Don't need to actually take any EBBs */ | |
63 | ||
64 | pid = fork(); | |
65 | if (pid == 0) | |
66 | exit(child()); | |
67 | ||
68 | /* Child does the actual testing */ | |
69 | FAIL_IF(wait_for_child(pid)); | |
70 | ||
71 | /* After fork */ | |
72 | event_close(&event); | |
73 | ||
74 | return 0; | |
75 | } | |
76 | ||
77 | int main(void) | |
78 | { | |
79 | return test_harness(fork_cleanup, "fork_cleanup"); | |
80 | } |