1/*
2 * Copyright (c) 2021 Apple Computer, 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#ifndef __KDP_COMMON_H
29#define __KDP_COMMON_H
30
31#ifdef XNU_KERNEL_PRIVATE
32
33#include <kern/task.h>
34#include <vm/vm_map.h>
35
36/*
37 * Wrapper around memcpy.
38 * This copies individual bytes if running in the panic context. Otherwise, this
39 * calls the standard memcpy function.
40 */
41void kdp_memcpy(void *dst, const void *src, size_t len);
42
43/*
44 * A version of strlcpy that is safe to run from the panic context. This calls
45 * kdp_memcpy() internally, which copies individual bytes if running in the panic context.
46 */
47size_t kdp_strlcpy(char *dst, const char *src, size_t maxlen);
48
49/*
50 * Get the page size from the specified vm map. This correctly handles K16/U4 (Rosetta) and
51 * K4/U16 (armv7k) environments.
52 */
53size_t kdp_vm_map_get_page_size(vm_map_t map, size_t *effective_page_mask);
54
55__options_closed_decl(kdp_fault_result_flags_t, uint32_t, {
56 KDP_FAULT_RESULT_PAGED_OUT = 0x1, /* some data was unable to be retrieved */
57 KDP_FAULT_RESULT_TRIED_FAULT = 0x2, /* tried to fault in data */
58 KDP_FAULT_RESULT_FAULTED_IN = 0x3, /* successfully faulted in data */
59});
60
61struct kdp_fault_result {
62 kdp_fault_result_flags_t flags;
63 uint64_t time_spent_faulting;
64};
65
66__options_closed_decl(kdp_fault_flags_t, uint32_t, {
67 KDP_FAULT_FLAGS_NONE = 0x0,
68 KDP_FAULT_FLAGS_ENABLE_FAULTING = 0x1, /* try faulting if pages are not resident */
69});
70
71__options_closed_decl(kdp_traverse_mappings_flags_t, uint32_t, {
72 KDP_TRAVERSE_MAPPINGS_FLAGS_NONE = 0x0,
73 KDP_TRAVERSE_MAPPINGS_FLAGS_PHYSICAL = 0x1 /* Use physical addresses instead of virtual addresses */
74});
75
76typedef int (*kdp_traverse_mappings_callback)(vm_offset_t start, vm_offset_t end, void *context);
77
78/*
79 * Traverse mappings in the specified task.
80 *
81 * - task The task
82 * - fault_flags Controls whether to fault in pages that are not resident.
83 * - traverse_mappings_flags Controls whether the callback is called with physical addresses
84 * - callback The callback is called for each memory region.
85 * - context Context passed to the callback.
86 */
87kern_return_t
88kdp_traverse_mappings(
89 task_t task,
90 kdp_fault_flags_t fault_flags,
91 kdp_traverse_mappings_flags_t traverse_mappings_flags,
92 kdp_traverse_mappings_callback callback,
93 void * context);
94
95/*
96 * Get dyld information from the specified task
97 *
98 * - task The task
99 * - fault_flags Controls whether to fault in pages that are not resident.
100 * - dyld_load_address The dyld load address is stored here.
101 * - dyld_uuid The dyld uuid is stored here.
102 * - task_page_size The task's page size is stored here.
103 */
104kern_return_t
105kdp_task_dyld_info(task_t task, kdp_fault_flags_t fault_flags, uint64_t * dyld_load_address, uuid_t dyld_uuid, size_t * task_page_size);
106
107/*
108 * Returns the physical address of the specified map:target address,
109 * using the kdp fault path if requested and the page is not resident.
110 */
111vm_offset_t kdp_find_phys(vm_map_t map, vm_offset_t target_addr, kdp_fault_flags_t fault_flags, struct kdp_fault_result *fault_results);
112
113/*
114 * Generic function to find a physical page for the specified map:target_addr.
115 */
116typedef vm_offset_t (*find_phys_fn_t)(vm_map_t map, vm_offset_t target_addr, kdp_fault_flags_t fault_flags, void * context);
117
118/*
119 * Generic copyin from userspace vm map.
120 *
121 * - map The vm map to use
122 * - uaddr Userspace VA to copy bytes from
123 * - dest Destination address
124 * - size Number of bytes to copy
125 * - fault_flags Controls whether to fault in pages that are not resident. This is passed to `find_phys_fn`.
126 * - find_phys_fn The function to use to return a physical address given a map and target address.
127 * If additional filtering/handling is not required, use `(find_phys_fn_t)kdp_find_phys`
128 * for this parameter.
129 * - context Reference context passed to find_phys_fn
130 *
131 * Copies in `size` bytes from `map:uaddr` to `dest`, using the specified function to find a physical address.
132 * Returns 0 if successful, an errno otherwise.
133 */
134int kdp_generic_copyin(vm_map_t map, uint64_t uaddr, void *dest, size_t size, kdp_fault_flags_t fault_flags, find_phys_fn_t find_phys_fn, void *context);
135
136/*
137 * Copies in a word from the specified task and address.
138 *
139 * - task The task to use
140 * - addr Address to copy from
141 * - result Where to store result
142 * - fault_flags Controls whether to fault in pages that are not resident. This is passed to `find_phys_fn`
143 * - find_phys_fn The function to use to return a physical address given a map and target address.
144 * If additional filtering/handling is not required, use `(find_phys_fn_t)kdp_find_phys`
145 * for this parameter.
146 * - context Reference context passed to find_phys_fn
147 *
148 * Returns 0 if successful, an errno otherwise.
149 */
150int kdp_generic_copyin_word(task_t task, uint64_t addr, uint64_t *result, kdp_fault_flags_t fault_flags, find_phys_fn_t find_phys_fn, void *context);
151
152/*
153 * Copies in a string from the specified task and address.
154 *
155 * - task The task to use
156 * - addr Address to copy from
157 * - buf Where to store result
158 * - buf_sz Size of destination buffer
159 * - fault_flags Controls whether to fault in pages that are not resident. This is passed to `find_phys_fn`
160 * - find_phys_fn The function to use to return a physical address given a map and target address.
161 * If additional filtering/handling is not required, use `(find_phys_fn_t)kdp_find_phys`
162 * for this parameter.
163 * - context Reference context passed to find_phys_fn
164 *
165 * Returns number of bytes copied if successful, -1 otherwise.
166 */
167int kdp_generic_copyin_string(task_t task, uint64_t addr, char *buf, int buf_sz, kdp_fault_flags_t fault_flags, find_phys_fn_t find_phys_fn, void *context);
168
169#endif /* XNU_KERNEL_PRIVATE */
170
171#endif /* __KDP_COMMON_H */
172