/*
* Copyright (c) 2021 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
#ifndef __KDP_COMMON_H
#define __KDP_COMMON_H
#ifdef XNU_KERNEL_PRIVATE
#include <kern/task.h>
#include <vm/vm_map.h>
/*
* Wrapper around memcpy.
* This copies individual bytes if running in the panic context. Otherwise, this
* calls the standard memcpy function.
*/
void kdp_memcpy(void *dst, const void *src, size_t len);
/*
* A version of strlcpy that is safe to run from the panic context. This calls
* kdp_memcpy() internally, which copies individual bytes if running in the panic context.
*/
size_t kdp_strlcpy(char *dst, const char *src, size_t maxlen);
/*
* Get the page size from the specified vm map. This correctly handles K16/U4 (Rosetta) and
* K4/U16 (armv7k) environments.
*/
size_t kdp_vm_map_get_page_size(vm_map_t map, size_t *effective_page_mask);
__options_closed_decl(kdp_fault_result_flags_t, uint32_t, {
KDP_FAULT_RESULT_PAGED_OUT = 0x1, /* some data was unable to be retrieved */
KDP_FAULT_RESULT_TRIED_FAULT = 0x2, /* tried to fault in data */
KDP_FAULT_RESULT_FAULTED_IN = 0x3, /* successfully faulted in data */
});
struct kdp_fault_result {
kdp_fault_result_flags_t flags;
uint64_t time_spent_faulting;
};
__options_closed_decl(kdp_fault_flags_t, uint32_t, {
KDP_FAULT_FLAGS_NONE = 0x0,
KDP_FAULT_FLAGS_ENABLE_FAULTING = 0x1, /* try faulting if pages are not resident */
KDP_FAULT_FLAGS_MULTICPU = 0x2, /* multicpu kdp context */
});
__options_closed_decl(kdp_traverse_mappings_flags_t, uint32_t, {
KDP_TRAVERSE_MAPPINGS_FLAGS_NONE = 0x0,
KDP_TRAVERSE_MAPPINGS_FLAGS_PHYSICAL = 0x1 /* Use physical addresses instead of virtual addresses */
});
typedef int (*kdp_traverse_mappings_callback)(vm_offset_t start, vm_offset_t end, void *context);
/*
* Traverse mappings in the specified task.
*
* - task The task
* - fault_flags Controls whether to fault in pages that are not resident.
* - traverse_mappings_flags Controls whether the callback is called with physical addresses
* - callback The callback is called for each memory region.
* - context Context passed to the callback.
*/
kern_return_t
kdp_traverse_mappings(
task_t task,
kdp_fault_flags_t fault_flags,
kdp_traverse_mappings_flags_t traverse_mappings_flags,
kdp_traverse_mappings_callback callback,
void * context);
/*
* Get dyld information from the specified task
*
* - task The task
* - fault_flags Controls whether to fault in pages that are not resident.
* - dyld_load_address The dyld load address is stored here.
* - dyld_uuid The dyld uuid is stored here.
* - task_page_size The task's page size is stored here.
*/
kern_return_t
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);
/*
* Returns the physical address of the specified map:target address,
* using the kdp fault path if requested and the page is not resident.
*/
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);
/*
* Generic function to find a physical page for the specified map:target_addr.
*/
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);
/*
* Generic copyin from userspace vm map.
*
* - map The vm map to use
* - uaddr Userspace VA to copy bytes from
* - dest Destination address
* - size Number of bytes to copy
* - fault_flags Controls whether to fault in pages that are not resident. This is passed to `find_phys_fn`.
* - find_phys_fn The function to use to return a physical address given a map and target address.
* If additional filtering/handling is not required, use `(find_phys_fn_t)kdp_find_phys`
* for this parameter.
* - context Reference context passed to find_phys_fn
*
* Copies in `size` bytes from `map:uaddr` to `dest`, using the specified function to find a physical address.
* Returns 0 if successful, an errno otherwise.
*/
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);
/*
* Copies in a word from the specified task and address.
*
* - task The task to use
* - addr Address to copy from
* - result Where to store result
* - fault_flags Controls whether to fault in pages that are not resident. This is passed to `find_phys_fn`
* - find_phys_fn The function to use to return a physical address given a map and target address.
* If additional filtering/handling is not required, use `(find_phys_fn_t)kdp_find_phys`
* for this parameter.
* - context Reference context passed to find_phys_fn
*
* Returns 0 if successful, an errno otherwise.
*/
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);
/*
* Copies in a string from the specified task and address.
*
* - task The task to use
* - addr Address to copy from
* - buf Where to store result
* - buf_sz Size of destination buffer
* - fault_flags Controls whether to fault in pages that are not resident. This is passed to `find_phys_fn`
* - find_phys_fn The function to use to return a physical address given a map and target address.
* If additional filtering/handling is not required, use `(find_phys_fn_t)kdp_find_phys`
* for this parameter.
* - context Reference context passed to find_phys_fn
*
* Returns number of bytes copied if successful, -1 otherwise.
*/
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);
#endif /* XNU_KERNEL_PRIVATE */
#endif /* __KDP_COMMON_H */