xref: /xnu-12377.61.12/tests/pmap_fault_on_commpage.c (revision 4d495c6e23c53686cf65f45067f79024cf5dcee8)
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