1 /*
2 * Copyright (c) 2000-2024 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <darwintest.h>
30 #include "mocks/unit_test_utils.h"
31 #include "mocks/mock_pmap.h"
32
33 #include <kdp/output_stages/output_stages.h>
34 #include <kdp/kdp_core.h>
35 #include <vm/pmap.h>
36 #include <arm/pmap_public.h>
37 #include <sys/queue.h>
38
39 #define UT_MODULE osfmk
40
41 kern_return_t
42 memory_backing_aware_buffer_stage_outproc(
43 struct kdp_output_stage *stage,
44 unsigned int request,
45 char *corename,
46 uint64_t length,
47 void * panic_data);
48
49 static kern_return_t
kosf_outproc_mock(__unused struct kdp_output_stage * stage,__unused unsigned int request,__unused char * corename,__unused uint64_t length,__unused void * panic_data)50 kosf_outproc_mock(
51 __unused struct kdp_output_stage *stage,
52 __unused unsigned int request,
53 __unused char *corename,
54 __unused uint64_t length,
55 __unused void *panic_data
56 )
57 {
58 return KERN_SUCCESS;
59 }
60
61 T_GLOBAL_META(
62 T_META_NAMESPACE("xnu.unit.panic_path_test"),
63 T_META_RADAR_COMPONENT_NAME("xnu"),
64 T_META_OWNER("e_zisman"),
65 T_META_RUN_CONCURRENTLY(false)
66 );
67
68 T_DECL(xnu_osfmk_kdp_memory_backing_aware_buffer_stage_outproc, "memory_backing_aware_buffer_stage_outproc")
69 {
70 // No need to actually fill with data.
71 char panic_data[18 * 1024] __attribute__((aligned));
72
73 STAILQ_HEAD(, kdp_output_stage) stages;
74 struct kdp_output_stage stage1;
75 struct kdp_output_stage stage2;
76 char data1[32];
77 char data2[32];
78
79 stage1.kos_data = data1;
80 stage2.kos_data = data2;
81 stage1.kos_funcs.kosf_outproc = kosf_outproc_mock;
82 stage2.kos_funcs.kosf_outproc = kosf_outproc_mock;
83
84 STAILQ_INIT(&stages);
85 STAILQ_INSERT_HEAD(&stages, &stage1, kos_next);
86 STAILQ_INSERT_TAIL(&stages, &stage2, kos_next);
87
88 struct {
89 char *test_name;
90 unsigned int pmap_cache_attributes_retval;
91 size_t panic_data_length;
92 kern_return_t expected;
93 } test_cases[] = {
94 {
95 .test_name = "normal memory flow",
96 .pmap_cache_attributes_retval = 0x02, // VM_WIMG_DEFAULT
97 .panic_data_length = sizeof(panic_data),
98 .expected = KERN_SUCCESS
99 },
100 {
101 .test_name = "not-normal memory flow, 4-byte reads",
102 .pmap_cache_attributes_retval = 0x00,
103 .panic_data_length = sizeof(panic_data),
104 .expected = KERN_SUCCESS
105 },
106 {
107 .test_name = "not-normal memory flow, 1-byte reads",
108 .pmap_cache_attributes_retval = 0x00,
109 .panic_data_length = sizeof(panic_data) - 1, // ensure length of panic data is not aligned to 4 bytes.
110 .expected = KERN_SUCCESS
111 },
112 };
113
114 T_MOCK_SET_RETVAL(kvtophys, pmap_paddr_t, 0x12345678); // arbitrary value; isn't used anyways since we mock pmap_cache_attributes.
115
116 for (size_t i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) {
117 T_MOCK_SET_RETVAL(pmap_cache_attributes, unsigned int, test_cases[i].pmap_cache_attributes_retval);
118
119 T_EXPECT_EQ(
120 test_cases[i].expected,
121 memory_backing_aware_buffer_stage_outproc(&stage1, KDP_DATA, "corename", sizeof(panic_data), panic_data),
122 "return value matches expectation"
123 );
124 }
125 }
126