2 * Copyright (c) 2008-2016 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/errno.h>
31 #include <mach/mach_types.h>
32 #include <mach/vm_attributes.h>
33 #include <mach/vm_param.h>
34 #include <libsa/types.h>
36 #include <vm/vm_map.h>
37 #include <i386/pmap.h>
38 #include <i386/pmap_internal.h> /* pmap_pde */
40 #include <i386/misc_protos.h>
42 #include <i386/proc_reg.h>
44 #include <i386/pmap_internal.h>
46 #include <kdp/kdp_internal.h>
47 #include <kdp/kdp_core.h>
48 #include <kdp/ml/i386/kdp_x86_common.h>
49 #include <mach/vm_map.h>
51 #include <vm/vm_protos.h>
52 #include <vm/vm_kern.h>
54 #include <machine/pal_routines.h>
55 #include <libkern/kernel_mach_header.h>
57 // #define KDP_VM_READ_DEBUG 1
58 // #define KDP_VM_WRITE_DEBUG 1
61 * A (potentially valid) physical address is not a kernel address
62 * i.e. it'a a user address.
64 #define IS_PHYS_ADDR(addr) IS_USERADDR64_CANONICAL(addr)
66 boolean_t kdp_read_io
;
67 boolean_t kdp_trans_off
;
69 pmap_paddr_t
kdp_vtophys(pmap_t pmap
, vm_offset_t va
);
73 kdp_jtag_coredump_t kdp_jtag_coredump
;
83 pp
= pmap_find_phys(pmap
, va
);
88 pa
= ((pmap_paddr_t
)pp
<< PAGE_SHIFT
) | (va
& PAGE_MASK
);
94 kdp_machine_vm_read( mach_vm_address_t src
, caddr_t dst
, mach_vm_size_t len
)
96 addr64_t cur_virt_src
= PAL_KDP_ADDR((addr64_t
)src
);
97 addr64_t cur_virt_dst
= PAL_KDP_ADDR((addr64_t
)(intptr_t)dst
);
98 addr64_t cur_phys_dst
, cur_phys_src
;
99 mach_vm_size_t resid
= len
;
100 mach_vm_size_t cnt
= 0, cnt_src
, cnt_dst
;
101 pmap_t src_pmap
= kernel_pmap
;
103 #ifdef KDP_VM_READ_DEBUG
104 printf("kdp_vm_read: src %llx dst %p len %llx\n", src
, (void *)dst
, len
);
107 if (kdp_trans_off
&& IS_PHYS_ADDR(src
)) {
108 kdp_readphysmem64_req_t rq
;
112 rq
.nbytes
= (uint32_t)len
;
113 ret
= kdp_machine_phys_read(&rq
, dst
, KDP_CURRENT_LCPU
);
117 /* If a different pmap has been specified with kdp_pmap, use it to translate the
118 * source (cur_virt_src); otherwise, the source is translated using the
126 if (!(cur_phys_src
= kdp_vtophys(src_pmap
,
131 /* Always translate the destination buffer using the kernel_pmap */
132 if (!(cur_phys_dst
= kdp_vtophys(kernel_pmap
, cur_virt_dst
))) {
136 /* Validate physical page numbers unless kdp_read_io is set */
137 if (kdp_read_io
== FALSE
) {
138 if (!pmap_valid_page(i386_btop(cur_phys_dst
)) || !pmap_valid_page(i386_btop(cur_phys_src
))) {
143 /* Get length left on page */
144 cnt_src
= PAGE_SIZE
- (cur_phys_src
& PAGE_MASK
);
145 cnt_dst
= PAGE_SIZE
- (cur_phys_dst
& PAGE_MASK
);
146 if (cnt_src
> cnt_dst
) {
155 /* Do a physical copy */
156 if (EFAULT
== ml_copy_phys(cur_phys_src
,
170 kdp_machine_phys_read(kdp_readphysmem64_req_t
*rq
, caddr_t dst
,
173 mach_vm_address_t src
= rq
->address
;
174 mach_vm_size_t len
= rq
->nbytes
;
176 addr64_t cur_virt_dst
;
177 addr64_t cur_phys_dst
, cur_phys_src
;
178 mach_vm_size_t resid
= len
;
179 mach_vm_size_t cnt
= 0, cnt_src
, cnt_dst
;
181 if ((lcpu
!= KDP_CURRENT_LCPU
) && (lcpu
!= cpu_number())) {
182 return (mach_vm_size_t
)
183 kdp_x86_xcpu_invoke(lcpu
, (kdp_x86_xcpu_func_t
)kdp_machine_phys_read
, rq
, dst
);
186 #ifdef KDP_VM_READ_DEBUG
187 printf("kdp_phys_read: src %llx dst %p len %llx\n", src
, (void *)dst
, len
);
190 cur_virt_dst
= (addr64_t
)(intptr_t)dst
;
191 cur_phys_src
= (addr64_t
)src
;
194 if (!(cur_phys_dst
= kdp_vtophys(kernel_pmap
, cur_virt_dst
))) {
198 /* Get length left on page */
199 cnt_src
= PAGE_SIZE
- (cur_phys_src
& PAGE_MASK
);
200 cnt_dst
= PAGE_SIZE
- (cur_phys_dst
& PAGE_MASK
);
201 if (cnt_src
> cnt_dst
) {
210 /* Do a physical copy; use ml_copy_phys() in the event this is
211 * a short read with potential side effects.
213 if (EFAULT
== ml_copy_phys(cur_phys_src
,
230 kdp_machine_vm_write( caddr_t src
, mach_vm_address_t dst
, mach_vm_size_t len
)
232 addr64_t cur_virt_src
, cur_virt_dst
;
233 addr64_t cur_phys_src
, cur_phys_dst
;
234 unsigned resid
, cnt
, cnt_src
, cnt_dst
;
236 #ifdef KDP_VM_WRITE_DEBUG
237 printf("kdp_vm_write: src %p dst %llx len %llx - %08X %08X\n", (void *)src
, dst
, len
, ((unsigned int *)src
)[0], ((unsigned int *)src
)[1]);
240 cur_virt_src
= PAL_KDP_ADDR((addr64_t
)(intptr_t)src
);
241 cur_virt_dst
= PAL_KDP_ADDR((addr64_t
)dst
);
243 resid
= (unsigned)len
;
246 if ((cur_phys_dst
= kdp_vtophys(kernel_pmap
, cur_virt_dst
)) == 0) {
250 if ((cur_phys_src
= kdp_vtophys(kernel_pmap
, cur_virt_src
)) == 0) {
254 /* Copy as many bytes as possible without crossing a page */
255 cnt_src
= (unsigned)(PAGE_SIZE
- (cur_phys_src
& PAGE_MASK
));
256 cnt_dst
= (unsigned)(PAGE_SIZE
- (cur_phys_dst
& PAGE_MASK
));
258 if (cnt_src
> cnt_dst
) {
267 if (EFAULT
== ml_copy_phys(cur_phys_src
, cur_phys_dst
, cnt
)) {
268 goto exit
; /* Copy stuff over */
282 kdp_machine_phys_write(kdp_writephysmem64_req_t
*rq
, caddr_t src
,
285 mach_vm_address_t dst
= rq
->address
;
286 mach_vm_size_t len
= rq
->nbytes
;
287 addr64_t cur_virt_src
;
288 addr64_t cur_phys_src
, cur_phys_dst
;
289 unsigned resid
, cnt
, cnt_src
, cnt_dst
;
291 if ((lcpu
!= KDP_CURRENT_LCPU
) && (lcpu
!= cpu_number())) {
292 return (mach_vm_size_t
)
293 kdp_x86_xcpu_invoke(lcpu
, (kdp_x86_xcpu_func_t
)kdp_machine_phys_write
, rq
, src
);
296 #ifdef KDP_VM_WRITE_DEBUG
297 printf("kdp_phys_write: src %p dst %llx len %llx - %08X %08X\n", (void *)src
, dst
, len
, ((unsigned int *)src
)[0], ((unsigned int *)src
)[1]);
300 cur_virt_src
= (addr64_t
)(intptr_t)src
;
301 cur_phys_dst
= (addr64_t
)dst
;
303 resid
= (unsigned)len
;
306 if ((cur_phys_src
= kdp_vtophys(kernel_pmap
, cur_virt_src
)) == 0) {
310 /* Copy as many bytes as possible without crossing a page */
311 cnt_src
= (unsigned)(PAGE_SIZE
- (cur_phys_src
& PAGE_MASK
));
312 cnt_dst
= (unsigned)(PAGE_SIZE
- (cur_phys_dst
& PAGE_MASK
));
314 if (cnt_src
> cnt_dst
) {
323 if (EFAULT
== ml_copy_phys(cur_phys_src
, cur_phys_dst
, cnt
)) {
324 goto exit
; /* Copy stuff over */
336 kdp_machine_ioport_read(kdp_readioport_req_t
*rq
, caddr_t data
, uint16_t lcpu
)
338 uint16_t addr
= rq
->address
;
339 uint16_t size
= rq
->nbytes
;
341 if ((lcpu
!= KDP_CURRENT_LCPU
) && (lcpu
!= cpu_number())) {
342 return (int) kdp_x86_xcpu_invoke(lcpu
, (kdp_x86_xcpu_func_t
)kdp_machine_ioport_read
, rq
, data
);
347 *((uint8_t *) data
) = inb(addr
);
350 *((uint16_t *) data
) = inw(addr
);
353 *((uint32_t *) data
) = inl(addr
);
356 return KDPERR_BADFLAVOR
;
359 return KDPERR_NO_ERROR
;
363 kdp_machine_ioport_write(kdp_writeioport_req_t
*rq
, caddr_t data
, uint16_t lcpu
)
365 uint16_t addr
= rq
->address
;
366 uint16_t size
= rq
->nbytes
;
368 if ((lcpu
!= KDP_CURRENT_LCPU
) && (lcpu
!= cpu_number())) {
369 return (int) kdp_x86_xcpu_invoke(lcpu
, (kdp_x86_xcpu_func_t
)kdp_machine_ioport_write
, rq
, data
);
374 outb(addr
, *((uint8_t *) data
));
377 outw(addr
, *((uint16_t *) data
));
380 outl(addr
, *((uint32_t *) data
));
383 return KDPERR_BADFLAVOR
;
386 return KDPERR_NO_ERROR
;
390 kdp_machine_msr64_read(kdp_readmsr64_req_t
*rq
, caddr_t data
, uint16_t lcpu
)
392 uint64_t *value
= (uint64_t *) data
;
393 uint32_t msr
= rq
->address
;
395 if ((lcpu
!= KDP_CURRENT_LCPU
) && (lcpu
!= cpu_number())) {
396 return (int) kdp_x86_xcpu_invoke(lcpu
, (kdp_x86_xcpu_func_t
)kdp_machine_msr64_read
, rq
, data
);
399 *value
= rdmsr64(msr
);
400 return KDPERR_NO_ERROR
;
404 kdp_machine_msr64_write(kdp_writemsr64_req_t
*rq
, caddr_t data
, uint16_t lcpu
)
406 uint64_t *value
= (uint64_t *) data
;
407 uint32_t msr
= rq
->address
;
409 if ((lcpu
!= KDP_CURRENT_LCPU
) && (lcpu
!= cpu_number())) {
410 return (int) kdp_x86_xcpu_invoke(lcpu
, (kdp_x86_xcpu_func_t
)kdp_machine_msr64_write
, rq
, data
);
413 wrmsr64(msr
, *value
);
414 return KDPERR_NO_ERROR
;
417 pt_entry_t
*debugger_ptep
;
418 vm_map_offset_t debugger_window_kva
;
420 /* Establish a pagetable window that can be remapped on demand.
421 * This is utilized by the debugger to address regions outside
426 kdp_map_debug_pagetable_window(void)
431 kr
= vm_map_find_space(kernel_map
,
432 &debugger_window_kva
,
435 VM_MAP_KERNEL_FLAGS_NONE
,
436 VM_KERN_MEMORY_OSFMK
,
439 if (kr
!= KERN_SUCCESS
) {
440 panic("%s: vm_map_find_space failed with %d\n", __FUNCTION__
, kr
);
443 vm_map_unlock(kernel_map
);
445 debugger_ptep
= pmap_pte(kernel_pmap
, debugger_window_kva
);
447 if (debugger_ptep
== NULL
) {
448 pmap_expand(kernel_pmap
, debugger_window_kva
, PMAP_EXPAND_OPTIONS_NONE
);
449 debugger_ptep
= pmap_pte(kernel_pmap
, debugger_window_kva
);
453 /* initialize kdp_jtag_coredump with data needed for JTAG coredump extraction */
456 kdp_jtag_coredump_init(void)
458 kdp_jtag_coredump
.version
= (uint64_t) KDP_JTAG_COREDUMP_VERSION_1
;
459 kdp_jtag_coredump
.kernel_map_start
= (uint64_t) kernel_map
->min_offset
;
460 kdp_jtag_coredump
.kernel_map_end
= (uint64_t) kernel_map
->max_offset
;
461 kdp_jtag_coredump
.kernel_pmap_pml4
= (uint64_t) kernel_pmap
->pm_pml4
;
462 kdp_jtag_coredump
.pmap_memory_regions
= (uint64_t) &pmap_memory_regions
;
463 kdp_jtag_coredump
.pmap_memory_region_count
= (uint64_t) pmap_memory_region_count
;
464 kdp_jtag_coredump
.pmap_memory_region_t_size
= (uint64_t) sizeof(pmap_memory_region_t
);
465 kdp_jtag_coredump
.physmap_base
= (uint64_t) &physmap_base
;
467 /* update signature last so that JTAG can trust that structure has valid data */
468 kdp_jtag_coredump
.signature
= (uint64_t) KDP_JTAG_COREDUMP_SIGNATURE
;
472 kdp_machine_init(void)
474 if (debug_boot_arg
== 0) {
478 kdp_map_debug_pagetable_window();
479 kdp_jtag_coredump_init();