2 * Copyright (c) 2000-2007 Apple Computer, 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 <mach/mach_types.h>
30 #include <sys/appleapiopts.h>
31 #include <kern/debug.h>
33 #include <kdp/kdp_internal.h>
34 #include <kdp/kdp_private.h>
36 #include <libsa/types.h>
38 #include <string.h> /* bcopy */
40 #include <kern/processor.h>
41 #include <kern/thread.h>
42 #include <vm/vm_map.h>
43 #include <vm/vm_kern.h>
45 #define DO_ALIGN 1 /* align all packet data accesses */
47 #define KDP_TEST_HARNESS 0
49 #define dprintf(x) kprintf x
55 dispatch_table
[KDP_INVALID_REQUEST
-KDP_CONNECT
] =
58 /* 1 */ kdp_disconnect
,
65 /* 8 */ kdp_writeregs
,
69 /* C */ kdp_resumecpus
,
72 /* F */ kdp_breakpoint_set
,
73 /*10 */ kdp_breakpoint_remove
,
77 /*14 */ kdp_readmem64
,
78 /*15 */ kdp_writemem64
,
79 /*16 */ kdp_breakpoint64_set
,
80 /*17 */ kdp_breakpoint64_remove
,
81 /*18 */ kdp_kernelversion
,
82 /*19 */ kdp_readphysmem64
,
83 /*20 */ kdp_writephysmem64
,
84 /*21 */ kdp_readioport
,
85 /*22 */ kdp_writeioport
,
86 /*23 */ kdp_readmsr64
,
87 /*24 */ kdp_writemsr64
,
92 #define MAX_BREAKPOINTS 100
95 * Version 11 of the KDP Protocol adds support for 64-bit wide memory
96 * addresses (read/write and breakpoints) as well as a dedicated
97 * kernelversion request. Version 12 adds read/writing of physical
98 * memory with 64-bit wide memory addresses.
100 #define KDP_VERSION 12
103 mach_vm_address_t address
;
105 uint8_t oldbytes
[MAX_BREAKINSN_BYTES
];
106 } kdp_breakpoint_record_t
;
108 static kdp_breakpoint_record_t breakpoint_list
[MAX_BREAKPOINTS
];
109 static unsigned int breakpoints_initialized
= 0;
111 int reattach_wait
= 0;
112 int noresume_on_disconnect
= 0;
113 extern unsigned int return_on_panic
;
115 typedef struct thread_snapshot
*thread_snapshot_t
;
118 machine_trace_thread(thread_t thread
, char *tracepos
, char *tracebound
, int nframes
, boolean_t user_p
);
120 machine_trace_thread64(thread_t thread
, char *tracepos
, char *tracebound
, int nframes
, boolean_t user_p
);
124 proc_name_kdp(task_t task
, char *buf
, int size
);
127 kdp_snapshot_postflight(void);
130 pid_from_task(task_t task
);
133 kdp_set_breakpoint_internal(
134 mach_vm_address_t address
138 kdp_remove_breakpoint_internal(
139 mach_vm_address_t address
144 kdp_stackshot(int pid
, void *tracebuf
, uint32_t tracebuf_size
, unsigned trace_options
, uint32_t *pbytesTraced
);
146 boolean_t
kdp_copyin(pmap_t
, uint64_t, void *, size_t);
147 extern void bcopy_phys(addr64_t
, addr64_t
, vm_size_t
);
149 extern char version
[];
155 unsigned short *reply_port
158 static unsigned aligned_pkt
[1538/sizeof(unsigned)+1]; // max ether pkt
159 kdp_pkt_t
*rd
= (kdp_pkt_t
*)&aligned_pkt
;
165 bcopy((char *)pkt
, (char *)rd
, sizeof(aligned_pkt
));
167 rd
= (kdp_pkt_t
*)pkt
;
169 if (plen
< sizeof (rd
->hdr
) || rd
->hdr
.len
!= plen
) {
170 printf("kdp_packet bad len pkt %lu hdr %d\n", plen
, rd
->hdr
.len
);
175 if (rd
->hdr
.is_reply
) {
176 printf("kdp_packet reply recvd req %x seq %x\n",
177 rd
->hdr
.request
, rd
->hdr
.seq
);
182 req
= rd
->hdr
.request
;
183 if (req
>= KDP_INVALID_REQUEST
) {
184 printf("kdp_packet bad request %x len %d seq %x key %x\n",
185 rd
->hdr
.request
, rd
->hdr
.len
, rd
->hdr
.seq
, rd
->hdr
.key
);
190 ret
= ((*dispatch_table
[req
- KDP_CONNECT
])(rd
, len
, reply_port
));
192 bcopy((char *)rd
, (char *) pkt
, *len
);
201 __unused
unsigned short *reply_port
204 kdp_pkt_t
*rd
= (kdp_pkt_t
*)pkt
;
206 printf("kdp_unknown request %x len %d seq %x key %x\n",
207 rd
->hdr
.request
, rd
->hdr
.len
, rd
->hdr
.seq
, rd
->hdr
.key
);
216 unsigned short *reply_port
219 kdp_connect_req_t
*rq
= &pkt
->connect_req
;
221 kdp_connect_reply_t
*rp
= &pkt
->connect_reply
;
223 if (plen
< sizeof (*rq
))
226 dprintf(("kdp_connect seq %x greeting %s\n", rq
->hdr
.seq
, rq
->greeting
));
229 if (rq
->hdr
.seq
== kdp
.conn_seq
) /* duplicate request */
230 rp
->error
= KDPERR_NO_ERROR
;
232 rp
->error
= KDPERR_ALREADY_CONNECTED
;
235 kdp
.reply_port
= rq
->req_reply_port
;
236 kdp
.exception_port
= rq
->exc_note_port
;
238 kdp
.conn_seq
= rq
->hdr
.seq
;
240 rp
->error
= KDPERR_NO_ERROR
;
243 rp
->hdr
.is_reply
= 1;
244 rp
->hdr
.len
= sizeof (*rp
);
246 *reply_port
= kdp
.reply_port
;
249 if (current_debugger
== KDP_CUR_DB
)
259 unsigned short *reply_port
262 kdp_disconnect_req_t
*rq
= &pkt
->disconnect_req
;
264 kdp_disconnect_reply_t
*rp
= &pkt
->disconnect_reply
;
266 if (plen
< sizeof (*rq
))
272 dprintf(("kdp_disconnect\n"));
274 *reply_port
= kdp
.reply_port
;
276 kdp
.reply_port
= kdp
.exception_port
= 0;
277 kdp
.is_halted
= kdp
.is_conn
= FALSE
;
278 kdp
.exception_seq
= kdp
.conn_seq
= 0;
280 if ((panicstr
!= NULL
) && (return_on_panic
== 0))
283 if (noresume_on_disconnect
== 1) {
285 noresume_on_disconnect
= 0;
288 rp
->hdr
.is_reply
= 1;
289 rp
->hdr
.len
= sizeof (*rp
);
293 if (current_debugger
== KDP_CUR_DB
)
303 unsigned short *reply_port
306 kdp_reattach_req_t
*rq
= &pkt
->reattach_req
;
309 kdp_disconnect(pkt
, len
, reply_port
);
310 *reply_port
= rq
->req_reply_port
;
319 unsigned short *reply_port
322 kdp_hostinfo_req_t
*rq
= &pkt
->hostinfo_req
;
324 kdp_hostinfo_reply_t
*rp
= &pkt
->hostinfo_reply
;
326 if (plen
< sizeof (*rq
))
329 dprintf(("kdp_hostinfo\n"));
331 rp
->hdr
.is_reply
= 1;
332 rp
->hdr
.len
= sizeof (*rp
);
334 kdp_machine_hostinfo(&rp
->hostinfo
);
336 *reply_port
= kdp
.reply_port
;
346 unsigned short *reply_port
349 kdp_kernelversion_req_t
*rq
= &pkt
->kernelversion_req
;
351 kdp_kernelversion_reply_t
*rp
= &pkt
->kernelversion_reply
;
354 if (plen
< sizeof (*rq
))
357 rp
->hdr
.is_reply
= 1;
358 rp
->hdr
.len
= sizeof (*rp
);
360 dprintf(("kdp_kernelversion\n"));
361 slen
= strlcpy(rp
->version
, version
, MAX_KDP_DATA_SIZE
);
363 rp
->hdr
.len
+= slen
+ 1; /* strlcpy returns the amount copied with NUL */
365 *reply_port
= kdp
.reply_port
;
375 unsigned short *reply_port
378 kdp_suspend_req_t
*rq
= &pkt
->suspend_req
;
380 kdp_suspend_reply_t
*rp
= &pkt
->suspend_reply
;
382 if (plen
< sizeof (*rq
))
385 rp
->hdr
.is_reply
= 1;
386 rp
->hdr
.len
= sizeof (*rp
);
388 dprintf(("kdp_suspend\n"));
390 kdp
.is_halted
= TRUE
;
392 *reply_port
= kdp
.reply_port
;
402 unsigned short *reply_port
405 kdp_resumecpus_req_t
*rq
= &pkt
->resumecpus_req
;
407 kdp_resumecpus_reply_t
*rp
= &pkt
->resumecpus_reply
;
409 if (plen
< sizeof (*rq
))
412 rp
->hdr
.is_reply
= 1;
413 rp
->hdr
.len
= sizeof (*rp
);
415 dprintf(("kdp_resumecpus %x\n", rq
->cpu_mask
));
417 kdp
.is_halted
= FALSE
;
419 *reply_port
= kdp
.reply_port
;
429 unsigned short *reply_port
432 kdp_writemem_req_t
*rq
= &pkt
->writemem_req
;
434 kdp_writemem_reply_t
*rp
= &pkt
->writemem_reply
;
437 if (plen
< sizeof (*rq
))
440 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
441 rp
->error
= KDPERR_BAD_NBYTES
;
443 dprintf(("kdp_writemem addr %x size %d\n", rq
->address
, rq
->nbytes
));
445 cnt
= kdp_machine_vm_write((caddr_t
)rq
->data
, (mach_vm_address_t
)rq
->address
, rq
->nbytes
);
446 rp
->error
= KDPERR_NO_ERROR
;
449 rp
->hdr
.is_reply
= 1;
450 rp
->hdr
.len
= sizeof (*rp
);
452 *reply_port
= kdp
.reply_port
;
462 unsigned short *reply_port
465 kdp_writemem64_req_t
*rq
= &pkt
->writemem64_req
;
467 kdp_writemem64_reply_t
*rp
= &pkt
->writemem64_reply
;
470 if (plen
< sizeof (*rq
))
473 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
474 rp
->error
= KDPERR_BAD_NBYTES
;
476 dprintf(("kdp_writemem64 addr %llx size %d\n", rq
->address
, rq
->nbytes
));
478 cnt
= kdp_machine_vm_write((caddr_t
)rq
->data
, (mach_vm_address_t
)rq
->address
, (mach_vm_size_t
)rq
->nbytes
);
479 rp
->error
= KDPERR_NO_ERROR
;
482 rp
->hdr
.is_reply
= 1;
483 rp
->hdr
.len
= sizeof (*rp
);
485 *reply_port
= kdp
.reply_port
;
495 unsigned short *reply_port
498 kdp_writephysmem64_req_t
*rq
= &pkt
->writephysmem64_req
;
500 kdp_writephysmem64_reply_t
*rp
= &pkt
->writephysmem64_reply
;
502 if (plen
< sizeof (*rq
))
505 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
506 rp
->error
= KDPERR_BAD_NBYTES
;
508 dprintf(("kdp_writephysmem64 addr %llx size %d\n", rq
->address
, rq
->nbytes
));
509 kdp_machine_phys_write(rq
, rq
->data
, rq
->lcpu
);
510 rp
->error
= KDPERR_NO_ERROR
;
513 rp
->hdr
.is_reply
= 1;
514 rp
->hdr
.len
= sizeof (*rp
);
516 *reply_port
= kdp
.reply_port
;
526 unsigned short *reply_port
529 kdp_readmem_req_t
*rq
= &pkt
->readmem_req
;
531 kdp_readmem_reply_t
*rp
= &pkt
->readmem_reply
;
533 #if __i386__ || __arm__
534 void *pversion
= &version
;
537 if (plen
< sizeof (*rq
))
540 rp
->hdr
.is_reply
= 1;
541 rp
->hdr
.len
= sizeof (*rp
);
543 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
544 rp
->error
= KDPERR_BAD_NBYTES
;
546 unsigned int n
= rq
->nbytes
;
548 dprintf(("kdp_readmem addr %x size %d\n", rq
->address
, n
));
549 #if __i386__ || __arm__
550 /* XXX This is a hack to facilitate the "showversion" macro
551 * on i386/ARM, which is used to obtain the kernel version without
552 * symbols - a pointer to the version string should eventually
553 * be pinned at a fixed address when an equivalent of the
554 * VECTORS segment (loaded at a fixed load address, and contains
555 * a table) is implemented on these architectures, as with PPC.
556 * N.B.: x86 now has a low global page, and the version indirection
557 * is pinned at 0x201C. We retain the 0x501C address override
558 * for compatibility. Future architectures should instead use
559 * the KDP_KERNELVERSION request.
561 if (rq
->address
== 0x501C)
562 rq
->address
= (uintptr_t)&pversion
;
564 cnt
= kdp_machine_vm_read((mach_vm_address_t
)rq
->address
, (caddr_t
)rp
->data
, n
);
565 rp
->error
= KDPERR_NO_ERROR
;
570 *reply_port
= kdp
.reply_port
;
580 unsigned short *reply_port
583 kdp_readmem64_req_t
*rq
= &pkt
->readmem64_req
;
585 kdp_readmem64_reply_t
*rp
= &pkt
->readmem64_reply
;
588 if (plen
< sizeof (*rq
))
591 rp
->hdr
.is_reply
= 1;
592 rp
->hdr
.len
= sizeof (*rp
);
594 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
595 rp
->error
= KDPERR_BAD_NBYTES
;
598 dprintf(("kdp_readmem64 addr %llx size %d\n", rq
->address
, rq
->nbytes
));
600 cnt
= kdp_machine_vm_read((mach_vm_address_t
)rq
->address
, (caddr_t
)rp
->data
, rq
->nbytes
);
601 rp
->error
= KDPERR_NO_ERROR
;
606 *reply_port
= kdp
.reply_port
;
616 unsigned short *reply_port
619 kdp_readphysmem64_req_t
*rq
= &pkt
->readphysmem64_req
;
621 kdp_readphysmem64_reply_t
*rp
= &pkt
->readphysmem64_reply
;
624 if (plen
< sizeof (*rq
))
627 rp
->hdr
.is_reply
= 1;
628 rp
->hdr
.len
= sizeof (*rp
);
630 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
631 rp
->error
= KDPERR_BAD_NBYTES
;
634 dprintf(("kdp_readphysmem64 addr %llx size %d\n", rq
->address
, rq
->nbytes
));
636 cnt
= (int)kdp_machine_phys_read(rq
, rp
->data
, rq
->lcpu
);
637 rp
->error
= KDPERR_NO_ERROR
;
642 *reply_port
= kdp
.reply_port
;
652 unsigned short *reply_port
655 kdp_maxbytes_req_t
*rq
= &pkt
->maxbytes_req
;
657 kdp_maxbytes_reply_t
*rp
= &pkt
->maxbytes_reply
;
659 if (plen
< sizeof (*rq
))
662 rp
->hdr
.is_reply
= 1;
663 rp
->hdr
.len
= sizeof (*rp
);
665 dprintf(("kdp_maxbytes\n"));
667 rp
->max_bytes
= MAX_KDP_DATA_SIZE
;
669 *reply_port
= kdp
.reply_port
;
679 unsigned short *reply_port
682 kdp_version_req_t
*rq
= &pkt
->version_req
;
684 kdp_version_reply_t
*rp
= &pkt
->version_reply
;
686 if (plen
< sizeof (*rq
))
689 rp
->hdr
.is_reply
= 1;
690 rp
->hdr
.len
= sizeof (*rp
);
692 dprintf(("kdp_version\n"));
694 rp
->version
= KDP_VERSION
;
695 if (!(kdp_flag
& KDP_BP_DIS
))
696 rp
->feature
= KDP_FEATURE_BP
;
700 *reply_port
= kdp
.reply_port
;
710 unsigned short *reply_port
713 kdp_regions_req_t
*rq
= &pkt
->regions_req
;
715 kdp_regions_reply_t
*rp
= &pkt
->regions_reply
;
718 if (plen
< sizeof (*rq
))
721 rp
->hdr
.is_reply
= 1;
722 rp
->hdr
.len
= sizeof (*rp
);
724 dprintf(("kdp_regions\n"));
730 r
->nbytes
= 0xffffffff;
732 r
->protection
= VM_PROT_ALL
; r
++; rp
->nregions
++;
734 rp
->hdr
.len
+= rp
->nregions
* sizeof (kdp_region_t
);
736 *reply_port
= kdp
.reply_port
;
746 unsigned short *reply_port
749 kdp_writeregs_req_t
*rq
= &pkt
->writeregs_req
;
752 kdp_writeregs_reply_t
*rp
= &pkt
->writeregs_reply
;
754 if (plen
< sizeof (*rq
))
757 size
= rq
->hdr
.len
- (unsigned)sizeof(kdp_hdr_t
) - (unsigned)sizeof(unsigned int);
758 rp
->error
= kdp_machine_write_regs(rq
->cpu
, rq
->flavor
, rq
->data
, &size
);
760 rp
->hdr
.is_reply
= 1;
761 rp
->hdr
.len
= sizeof (*rp
);
763 *reply_port
= kdp
.reply_port
;
773 unsigned short *reply_port
776 kdp_readregs_req_t
*rq
= &pkt
->readregs_req
;
778 kdp_readregs_reply_t
*rp
= &pkt
->readregs_reply
;
781 if (plen
< sizeof (*rq
))
784 rp
->hdr
.is_reply
= 1;
785 rp
->hdr
.len
= sizeof (*rp
);
787 rp
->error
= kdp_machine_read_regs(rq
->cpu
, rq
->flavor
, rp
->data
, &size
);
790 *reply_port
= kdp
.reply_port
;
801 unsigned short *reply_port
804 kdp_breakpoint_req_t
*rq
= &pkt
->breakpoint_req
;
805 kdp_breakpoint_reply_t
*rp
= &pkt
->breakpoint_reply
;
809 if (plen
< sizeof (*rq
))
812 dprintf(("kdp_breakpoint_set %x\n", rq
->address
));
814 kerr
= kdp_set_breakpoint_internal((mach_vm_address_t
)rq
->address
);
818 rp
->hdr
.is_reply
= 1;
819 rp
->hdr
.len
= sizeof (*rp
);
820 *reply_port
= kdp
.reply_port
;
827 kdp_breakpoint64_set(
830 unsigned short *reply_port
833 kdp_breakpoint64_req_t
*rq
= &pkt
->breakpoint64_req
;
834 kdp_breakpoint64_reply_t
*rp
= &pkt
->breakpoint64_reply
;
838 if (plen
< sizeof (*rq
))
841 dprintf(("kdp_breakpoint64_set %llx\n", rq
->address
));
843 kerr
= kdp_set_breakpoint_internal((mach_vm_address_t
)rq
->address
);
847 rp
->hdr
.is_reply
= 1;
848 rp
->hdr
.len
= sizeof (*rp
);
849 *reply_port
= kdp
.reply_port
;
856 kdp_breakpoint_remove(
859 unsigned short *reply_port
862 kdp_breakpoint_req_t
*rq
= &pkt
->breakpoint_req
;
863 kdp_breakpoint_reply_t
*rp
= &pkt
->breakpoint_reply
;
866 if (plen
< sizeof (*rq
))
869 dprintf(("kdp_breakpoint_remove %x\n", rq
->address
));
871 kerr
= kdp_remove_breakpoint_internal((mach_vm_address_t
)rq
->address
);
875 rp
->hdr
.is_reply
= 1;
876 rp
->hdr
.len
= sizeof (*rp
);
877 *reply_port
= kdp
.reply_port
;
884 kdp_breakpoint64_remove(
887 unsigned short *reply_port
890 kdp_breakpoint64_req_t
*rq
= &pkt
->breakpoint64_req
;
891 kdp_breakpoint64_reply_t
*rp
= &pkt
->breakpoint64_reply
;
895 if (plen
< sizeof (*rq
))
898 dprintf(("kdp_breakpoint64_remove %llx\n", rq
->address
));
900 kerr
= kdp_remove_breakpoint_internal((mach_vm_address_t
)rq
->address
);
904 rp
->hdr
.is_reply
= 1;
905 rp
->hdr
.len
= sizeof (*rp
);
906 *reply_port
= kdp
.reply_port
;
914 kdp_set_breakpoint_internal(
915 mach_vm_address_t address
919 uint8_t breakinstr
[MAX_BREAKINSN_BYTES
], oldinstr
[MAX_BREAKINSN_BYTES
];
920 uint32_t breakinstrsize
= sizeof(breakinstr
);
924 kdp_machine_get_breakinsn(breakinstr
, &breakinstrsize
);
926 if(breakpoints_initialized
== 0)
928 for(i
=0;(i
< MAX_BREAKPOINTS
); breakpoint_list
[i
].address
=0, i
++);
929 breakpoints_initialized
++;
932 cnt
= kdp_machine_vm_read(address
, (caddr_t
)&oldinstr
, (mach_vm_size_t
)breakinstrsize
);
934 if (0 == memcmp(oldinstr
, breakinstr
, breakinstrsize
)) {
935 printf("A trap was already set at that address, not setting new breakpoint\n");
937 return KDPERR_BREAKPOINT_ALREADY_SET
;
940 for(i
=0;(i
< MAX_BREAKPOINTS
) && (breakpoint_list
[i
].address
!= 0); i
++);
942 if (i
== MAX_BREAKPOINTS
) {
943 return KDPERR_MAX_BREAKPOINTS
;
946 breakpoint_list
[i
].address
= address
;
947 memcpy(breakpoint_list
[i
].oldbytes
, oldinstr
, breakinstrsize
);
948 breakpoint_list
[i
].bytesused
= breakinstrsize
;
950 cnt
= kdp_machine_vm_write((caddr_t
)&breakinstr
, address
, breakinstrsize
);
952 return KDPERR_NO_ERROR
;
956 kdp_remove_breakpoint_internal(
957 mach_vm_address_t address
963 for(i
=0;(i
< MAX_BREAKPOINTS
) && (breakpoint_list
[i
].address
!= address
); i
++);
965 if (i
== MAX_BREAKPOINTS
)
967 return KDPERR_BREAKPOINT_NOT_FOUND
;
970 breakpoint_list
[i
].address
= 0;
971 cnt
= kdp_machine_vm_write((caddr_t
)&breakpoint_list
[i
].oldbytes
, address
, breakpoint_list
[i
].bytesused
);
973 return KDPERR_NO_ERROR
;
977 kdp_remove_all_breakpoints(void)
980 boolean_t breakpoint_found
= FALSE
;
982 if (breakpoints_initialized
)
984 for(i
=0;i
< MAX_BREAKPOINTS
; i
++)
986 if (breakpoint_list
[i
].address
)
988 kdp_machine_vm_write((caddr_t
)&(breakpoint_list
[i
].oldbytes
), (mach_vm_address_t
)breakpoint_list
[i
].address
, (mach_vm_size_t
)breakpoint_list
[i
].bytesused
);
989 breakpoint_found
= TRUE
;
990 breakpoint_list
[i
].address
= 0;
994 if (breakpoint_found
)
995 printf("kdp_remove_all_breakpoints: found extant breakpoints, removing them.\n");
997 return breakpoint_found
;
1002 __unused kdp_pkt_t
*pkt
,
1004 __unused
unsigned short *reply_port
1007 dprintf(("kdp_reboot\n"));
1009 kdp_machine_reboot();
1011 return (TRUE
); // no, not really, we won't return
1014 #define MAX_FRAMES 1000
1016 static int pid_from_task(task_t task
)
1021 pid
= proc_pid(task
->bsd_info
);
1027 kdp_copyin(pmap_t p
, uint64_t uaddr
, void *dest
, size_t size
) {
1029 char *kvaddr
= dest
;
1032 ppnum_t upn
= pmap_find_phys(p
, uaddr
);
1033 uint64_t phys_src
= (upn
<< PAGE_SHIFT
) | (uaddr
& PAGE_MASK
);
1034 uint64_t phys_dest
= kvtophys((vm_offset_t
)kvaddr
);
1035 uint64_t src_rem
= PAGE_SIZE
- (phys_src
& PAGE_MASK
);
1036 uint64_t dst_rem
= PAGE_SIZE
- (phys_dest
& PAGE_MASK
);
1037 size_t cur_size
= (uint32_t) MIN(src_rem
, dst_rem
);
1038 cur_size
= MIN(cur_size
, rem
);
1040 if (upn
&& pmap_valid_page(upn
) && phys_dest
) {
1041 bcopy_phys(phys_src
, phys_dest
, cur_size
);
1053 kdp_stackshot(int pid
, void *tracebuf
, uint32_t tracebuf_size
, unsigned trace_options
, uint32_t *pbytesTraced
)
1055 char *tracepos
= (char *) tracebuf
;
1056 char *tracebound
= tracepos
+ tracebuf_size
;
1057 uint32_t tracebytes
= 0;
1060 task_t task
= TASK_NULL
;
1061 thread_t thread
= THREAD_NULL
;
1062 int nframes
= trace_options
;
1063 thread_snapshot_t tsnap
= NULL
;
1064 unsigned framesize
= 2 * sizeof(vm_offset_t
);
1065 boolean_t dispatch_p
= ((trace_options
& STACKSHOT_GET_DQ
) != 0);
1066 uint16_t dispatch_offset
= (trace_options
& STACKSHOT_DISPATCH_OFFSET_MASK
) >> STACKSHOT_DISPATCH_OFFSET_SHIFT
;
1068 struct thread cthread
;
1070 if ((nframes
<= 0) || nframes
> MAX_FRAMES
)
1071 nframes
= MAX_FRAMES
;
1073 queue_iterate(&tasks
, task
, task_t
, tasks
) {
1074 if ((task
== NULL
) || (ml_nofault_copy((vm_offset_t
) task
, (vm_offset_t
) &ctask
, sizeof(struct task
)) != sizeof(struct task
)))
1076 /* Trace everything, unless a process was specified */
1077 if ((pid
== -1) || (pid
== pid_from_task(task
)))
1078 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
){
1079 if ((thread
== NULL
) || (ml_nofault_copy((vm_offset_t
) thread
, (vm_offset_t
) &cthread
, sizeof(struct thread
)) != sizeof(struct thread
)))
1081 if (((tracepos
+ 4 * sizeof(struct thread_snapshot
)) > tracebound
)) {
1085 /* Populate the thread snapshot header */
1086 tsnap
= (thread_snapshot_t
) tracepos
;
1087 tsnap
->thread_id
= (uint64_t) (uintptr_t)thread
;
1088 tsnap
->state
= thread
->state
;
1089 tsnap
->wait_event
= thread
->wait_event
;
1090 tsnap
->continuation
= (uint64_t) (uintptr_t) thread
->continuation
;
1091 /* Add the BSD process identifiers */
1092 if ((tsnap
->pid
= pid_from_task(task
)) != -1)
1093 proc_name_kdp(task
, tsnap
->p_comm
, sizeof(tsnap
->p_comm
));
1095 tsnap
->p_comm
[0] = '\0';
1097 tsnap
->snapshot_magic
= 0xfeedface;
1098 tracepos
+= sizeof(struct thread_snapshot
);
1099 tsnap
->ss_flags
= 0;
1101 if (dispatch_p
&& (task
!= kernel_task
) && (task
->active
) && (task
->map
)) {
1102 uint64_t dqkeyaddr
= thread_dispatchqaddr(thread
);
1103 if (dqkeyaddr
!= 0) {
1104 boolean_t task64
= task_has_64BitAddr(task
);
1105 uint64_t dqaddr
= 0;
1106 if (kdp_copyin(task
->map
->pmap
, dqkeyaddr
, &dqaddr
, (task64
? 8 : 4)) && (dqaddr
!= 0)) {
1107 uint64_t dqserialnumaddr
= dqaddr
+ dispatch_offset
;
1108 uint64_t dqserialnum
= 0;
1109 if (kdp_copyin(task
->map
->pmap
, dqserialnumaddr
, &dqserialnum
, (task64
? 8 : 4))) {
1110 tsnap
->ss_flags
|= kHasDispatchSerial
;
1111 *(uint64_t *)tracepos
= dqserialnum
;
1117 /* Call through to the machine specific trace routines
1118 * Frames are added past the snapshot header.
1120 if (thread
->kernel_stack
!= 0) {
1121 #if defined(__LP64__)
1122 tracebytes
= machine_trace_thread64(thread
, tracepos
, tracebound
, nframes
, FALSE
);
1123 tsnap
->ss_flags
|= kKernel64_p
;
1126 tracebytes
= machine_trace_thread(thread
, tracepos
, tracebound
, nframes
, FALSE
);
1130 tsnap
->nkern_frames
= tracebytes
/framesize
;
1131 tracepos
+= tracebytes
;
1133 /* Trace user stack, if any */
1134 if (thread
->task
->map
!= kernel_map
) {
1136 if (task_has_64BitAddr(thread
->task
)) {
1137 tracebytes
= machine_trace_thread64(thread
, tracepos
, tracebound
, nframes
, TRUE
);
1138 tsnap
->ss_flags
|= kUser64_p
;
1142 tracebytes
= machine_trace_thread(thread
, tracepos
, tracebound
, nframes
, TRUE
);
1146 tsnap
->nuser_frames
= tracebytes
/framesize
;
1147 tracepos
+= tracebytes
;
1153 /* Release stack snapshot wait indicator */
1154 kdp_snapshot_postflight();
1156 *pbytesTraced
= (uint32_t)(tracepos
- (char *) tracebuf
);
1162 kdp_readioport(kdp_pkt_t
*pkt
,
1164 unsigned short *reply_port
1167 kdp_readioport_req_t
*rq
= &pkt
->readioport_req
;
1168 kdp_readioport_reply_t
*rp
= &pkt
->readioport_reply
;
1171 if (plen
< sizeof (*rq
))
1174 rp
->hdr
.is_reply
= 1;
1175 rp
->hdr
.len
= sizeof (*rp
);
1177 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
1178 rp
->error
= KDPERR_BAD_NBYTES
;
1180 #if KDP_TEST_HARNESS
1181 uint16_t addr
= rq
->address
;
1183 uint16_t size
= rq
->nbytes
;
1184 dprintf(("kdp_readioport addr %x size %d\n", addr
, size
));
1186 rp
->error
= kdp_machine_ioport_read(rq
, rp
->data
, rq
->lcpu
);
1187 if (rp
->error
== KDPERR_NO_ERROR
)
1188 rp
->hdr
.len
+= size
;
1191 *reply_port
= kdp
.reply_port
;
1201 unsigned short *reply_port
1204 kdp_writeioport_req_t
*rq
= &pkt
->writeioport_req
;
1205 kdp_writeioport_reply_t
*rp
= &pkt
->writeioport_reply
;
1208 if (plen
< sizeof (*rq
))
1211 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
1212 rp
->error
= KDPERR_BAD_NBYTES
;
1214 dprintf(("kdp_writeioport addr %x size %d\n", rq
->address
,
1217 rp
->error
= kdp_machine_ioport_write(rq
, rq
->data
, rq
->lcpu
);
1220 rp
->hdr
.is_reply
= 1;
1221 rp
->hdr
.len
= sizeof (*rp
);
1223 *reply_port
= kdp
.reply_port
;
1230 kdp_readmsr64(kdp_pkt_t
*pkt
,
1232 unsigned short *reply_port
1235 kdp_readmsr64_req_t
*rq
= &pkt
->readmsr64_req
;
1236 kdp_readmsr64_reply_t
*rp
= &pkt
->readmsr64_reply
;
1239 if (plen
< sizeof (*rq
))
1242 rp
->hdr
.is_reply
= 1;
1243 rp
->hdr
.len
= sizeof (*rp
);
1245 dprintf(("kdp_readmsr64 lcpu %x addr %x\n", rq
->lcpu
, rq
->address
));
1246 rp
->error
= kdp_machine_msr64_read(rq
, rp
->data
, rq
->lcpu
);
1247 if (rp
->error
== KDPERR_NO_ERROR
)
1248 rp
->hdr
.len
+= sizeof(uint64_t);
1250 *reply_port
= kdp
.reply_port
;
1260 unsigned short *reply_port
1263 kdp_writemsr64_req_t
*rq
= &pkt
->writemsr64_req
;
1264 kdp_writemsr64_reply_t
*rp
= &pkt
->writemsr64_reply
;
1267 if (plen
< sizeof (*rq
))
1270 dprintf(("kdp_writemsr64 lcpu %x addr %x\n", rq
->lcpu
, rq
->address
));
1271 rp
->error
= kdp_machine_msr64_write(rq
, rq
->data
, rq
->lcpu
);
1273 rp
->hdr
.is_reply
= 1;
1274 rp
->hdr
.len
= sizeof (*rp
);
1276 *reply_port
= kdp
.reply_port
;