1 #include <darwintest.h>
2 #include <machine/cpu_capabilities.h>
3 #include "test_utils.h"
4
5 #include <stdlib.h>
6 #include <signal.h>
7
8 T_GLOBAL_META(
9 T_META_NAMESPACE("xnu.arm"),
10 T_META_RADAR_COMPONENT_NAME("xnu"),
11 T_META_RADAR_COMPONENT_VERSION("arm"),
12 T_META_ENABLED(TARGET_CPU_ARM64),
13 T_META_OWNER("xi_han"),
14 T_META_RUN_CONCURRENTLY(true),
15 XNU_T_META_SOC_SPECIFIC
16 );
17
18 #if defined(__LP64__)
19 #define SIGNAL_EXPECTED SIGBUS
20 #define SIGNAL_EXPECTED_STR "SIGBUS"
21 #else
22 /* On arm64_32, _COMM_PAGE_START_ADDRESS is out of normal VA range, so a SIGSEGV is expected if there's a fault. */
23 #define SIGNAL_EXPECTED SIGSEGV
24 #define SIGNAL_EXPECTED_STR "SIGSEGV"
25 #endif
26
27 #define TEST_STATE_TESTING_NONE 0
28 #define TEST_STATE_TESTING_READ 1
29 #define TEST_STATE_TESTING_WRITE 2
30 static volatile sig_atomic_t test_state;
31
32 static void
test_handler(int signum)33 test_handler(int signum)
34 {
35 T_ASSERT_EQ(signum, SIGNAL_EXPECTED, "received signal");
36
37 if (test_state == TEST_STATE_TESTING_READ) {
38 T_FAIL("read access triggered a %s", SIGNAL_EXPECTED_STR);
39 } else if (test_state == TEST_STATE_TESTING_WRITE) {
40 T_PASS("write access triggered a %s", SIGNAL_EXPECTED_STR);
41 exit(EXIT_SUCCESS);
42 } else {
43 T_FAIL("unexpected %s in test state %u", SIGNAL_EXPECTED_STR, (unsigned int)test_state);
44 }
45 }
46
47 T_DECL(pmap_commpage_access_test,
48 "Verify system behavior on user access to the commpage", T_META_TAG_VM_NOT_PREFERRED)
49 {
50 test_state = TEST_STATE_TESTING_NONE;
51
52 struct sigaction sa;
53 sa.sa_handler = test_handler;
54 sa.sa_mask = 0;
55 sa.sa_flags = 0;
56 sigaction(SIGNAL_EXPECTED, &sa, NULL);
57
58 test_state = TEST_STATE_TESTING_READ;
59 *(volatile uint32_t *)_COMM_PAGE_START_ADDRESS;
60
61 T_PASS("read access must not trigger a %s", SIGNAL_EXPECTED_STR);
62
63 test_state = TEST_STATE_TESTING_WRITE;
64 *(volatile uint32_t *)_COMM_PAGE_START_ADDRESS = 0;
65
66 T_FAIL("write access must trigger a %s", SIGNAL_EXPECTED_STR);
67 }
68