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 */ 41 void 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 */ 47 size_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 */ 53 size_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 61 struct 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 KDP_FAULT_FLAGS_MULTICPU = 0x2, /* multicpu kdp context */ 70 }); 71 72 __options_closed_decl(kdp_traverse_mappings_flags_t, uint32_t, { 73 KDP_TRAVERSE_MAPPINGS_FLAGS_NONE = 0x0, 74 KDP_TRAVERSE_MAPPINGS_FLAGS_PHYSICAL = 0x1 /* Use physical addresses instead of virtual addresses */ 75 }); 76 77 typedef int (*kdp_traverse_mappings_callback)(vm_offset_t start, vm_offset_t end, void *context); 78 79 /* 80 * Traverse mappings in the specified task. 81 * 82 * - task The task 83 * - fault_flags Controls whether to fault in pages that are not resident. 84 * - traverse_mappings_flags Controls whether the callback is called with physical addresses 85 * - callback The callback is called for each memory region. 86 * - context Context passed to the callback. 87 */ 88 kern_return_t 89 kdp_traverse_mappings( 90 task_t task, 91 kdp_fault_flags_t fault_flags, 92 kdp_traverse_mappings_flags_t traverse_mappings_flags, 93 kdp_traverse_mappings_callback callback, 94 void * context); 95 96 /* 97 * Get dyld information from the specified task 98 * 99 * - task The task 100 * - fault_flags Controls whether to fault in pages that are not resident. 101 * - dyld_load_address The dyld load address is stored here. 102 * - dyld_uuid The dyld uuid is stored here. 103 * - task_page_size The task's page size is stored here. 104 */ 105 kern_return_t 106 kdp_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); 107 108 /* 109 * Returns the physical address of the specified map:target address, 110 * using the kdp fault path if requested and the page is not resident. 111 */ 112 vm_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); 113 114 /* 115 * Generic function to find a physical page for the specified map:target_addr. 116 */ 117 typedef vm_offset_t (*find_phys_fn_t)(vm_map_t map, vm_offset_t target_addr, kdp_fault_flags_t fault_flags, void * context); 118 119 /* 120 * Generic copyin from userspace vm map. 121 * 122 * - map The vm map to use 123 * - uaddr Userspace VA to copy bytes from 124 * - dest Destination address 125 * - size Number of bytes to copy 126 * - fault_flags Controls whether to fault in pages that are not resident. This is passed to `find_phys_fn`. 127 * - find_phys_fn The function to use to return a physical address given a map and target address. 128 * If additional filtering/handling is not required, use `(find_phys_fn_t)kdp_find_phys` 129 * for this parameter. 130 * - context Reference context passed to find_phys_fn 131 * 132 * Copies in `size` bytes from `map:uaddr` to `dest`, using the specified function to find a physical address. 133 * Returns 0 if successful, an errno otherwise. 134 */ 135 int 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); 136 137 /* 138 * Copies in a word from the specified task and address. 139 * 140 * - task The task to use 141 * - addr Address to copy from 142 * - result Where to store result 143 * - fault_flags Controls whether to fault in pages that are not resident. This is passed to `find_phys_fn` 144 * - find_phys_fn The function to use to return a physical address given a map and target address. 145 * If additional filtering/handling is not required, use `(find_phys_fn_t)kdp_find_phys` 146 * for this parameter. 147 * - context Reference context passed to find_phys_fn 148 * 149 * Returns 0 if successful, an errno otherwise. 150 */ 151 int 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); 152 153 /* 154 * Copies in a string from the specified task and address. 155 * 156 * - task The task to use 157 * - addr Address to copy from 158 * - buf Where to store result 159 * - buf_sz Size of destination buffer 160 * - fault_flags Controls whether to fault in pages that are not resident. This is passed to `find_phys_fn` 161 * - find_phys_fn The function to use to return a physical address given a map and target address. 162 * If additional filtering/handling is not required, use `(find_phys_fn_t)kdp_find_phys` 163 * for this parameter. 164 * - context Reference context passed to find_phys_fn 165 * 166 * Returns number of bytes copied if successful, -1 otherwise. 167 */ 168 int 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); 169 170 #endif /* XNU_KERNEL_PRIVATE */ 171 172 #endif /* __KDP_COMMON_H */ 173