]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kdp/kdp.c
xnu-4570.1.46.tar.gz
[apple/xnu.git] / osfmk / kdp / kdp.c
1 /*
2 * Copyright (c) 2000-2012 Apple 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
29 #include <mach/mach_types.h>
30 #include <mach/vm_param.h>
31 #include <sys/appleapiopts.h>
32 #include <kern/debug.h>
33 #include <uuid/uuid.h>
34
35 #include <kdp/kdp_internal.h>
36 #include <kdp/kdp_private.h>
37 #include <kdp/kdp_core.h>
38
39 #include <libsa/types.h>
40 #include <libkern/version.h>
41
42 #include <string.h> /* bcopy */
43
44 #include <kern/processor.h>
45 #include <kern/thread.h>
46 #include <kern/clock.h>
47 #include <vm/vm_map.h>
48 #include <vm/vm_kern.h>
49 #include <vm/vm_pageout.h>
50 #include <vm/vm_shared_region.h>
51 #include <libkern/OSKextLibPrivate.h>
52
53 #define DO_ALIGN 1 /* align all packet data accesses */
54
55 #define KDP_TEST_HARNESS 0
56 #if KDP_TEST_HARNESS
57 #define dprintf(x) kprintf x
58 #else
59 #define dprintf(x)
60 #endif
61
62 static kdp_dispatch_t
63 dispatch_table[KDP_INVALID_REQUEST-KDP_CONNECT] =
64 {
65 /* 0 */ kdp_connect,
66 /* 1 */ kdp_disconnect,
67 /* 2 */ kdp_hostinfo,
68 /* 3 */ kdp_version,
69 /* 4 */ kdp_maxbytes,
70 /* 5 */ kdp_readmem,
71 /* 6 */ kdp_writemem,
72 /* 7 */ kdp_readregs,
73 /* 8 */ kdp_writeregs,
74 /* 9 */ kdp_unknown,
75 /* A */ kdp_unknown,
76 /* B */ kdp_suspend,
77 /* C */ kdp_resumecpus,
78 /* D */ kdp_unknown,
79 /* E */ kdp_unknown,
80 /* F */ kdp_breakpoint_set,
81 /*10 */ kdp_breakpoint_remove,
82 /*11 */ kdp_regions,
83 /*12 */ kdp_reattach,
84 /*13 */ kdp_reboot,
85 /*14 */ kdp_readmem64,
86 /*15 */ kdp_writemem64,
87 /*16 */ kdp_breakpoint64_set,
88 /*17 */ kdp_breakpoint64_remove,
89 /*18 */ kdp_kernelversion,
90 /*19 */ kdp_readphysmem64,
91 /*1A */ kdp_writephysmem64,
92 /*1B */ kdp_readioport,
93 /*1C */ kdp_writeioport,
94 /*1D */ kdp_readmsr64,
95 /*1E */ kdp_writemsr64,
96 /*1F */ kdp_dumpinfo,
97 };
98
99 kdp_glob_t kdp;
100
101 #define MAX_BREAKPOINTS 100
102
103 /*
104 * Version 11 of the KDP Protocol adds support for 64-bit wide memory
105 * addresses (read/write and breakpoints) as well as a dedicated
106 * kernelversion request. Version 12 adds read/writing of physical
107 * memory with 64-bit wide memory addresses.
108 */
109 #define KDP_VERSION 12
110
111 typedef struct{
112 mach_vm_address_t address;
113 uint32_t bytesused;
114 uint8_t oldbytes[MAX_BREAKINSN_BYTES];
115 } kdp_breakpoint_record_t;
116
117 static kdp_breakpoint_record_t breakpoint_list[MAX_BREAKPOINTS];
118 static unsigned int breakpoints_initialized = 0;
119
120 int reattach_wait = 0;
121 int noresume_on_disconnect = 0;
122
123 kdp_error_t
124 kdp_set_breakpoint_internal(
125 mach_vm_address_t address
126 );
127
128 kdp_error_t
129 kdp_remove_breakpoint_internal(
130 mach_vm_address_t address
131 );
132
133 boolean_t
134 kdp_packet(
135 unsigned char *pkt,
136 int *len,
137 unsigned short *reply_port
138 )
139 {
140 static unsigned aligned_pkt[1538/sizeof(unsigned)+1]; // max ether pkt
141 kdp_pkt_t *rd = (kdp_pkt_t *)&aligned_pkt;
142 size_t plen = *len;
143 kdp_req_t req;
144 boolean_t ret;
145
146 #if DO_ALIGN
147 if (plen > sizeof(aligned_pkt)) {
148 printf("kdp_packet bad len %lu\n", plen);
149 return FALSE;
150 }
151 bcopy((char *)pkt, (char *)rd, plen);
152 #else
153 rd = (kdp_pkt_t *)pkt;
154 #endif
155 if (plen < sizeof (rd->hdr) || rd->hdr.len != plen) {
156 printf("kdp_packet bad len pkt %lu hdr %d\n", plen, rd->hdr.len);
157
158 return (FALSE);
159 }
160
161 if (rd->hdr.is_reply) {
162 printf("kdp_packet reply recvd req %x seq %x\n",
163 rd->hdr.request, rd->hdr.seq);
164
165 return (FALSE);
166 }
167
168 req = rd->hdr.request;
169 if (req >= KDP_INVALID_REQUEST) {
170 printf("kdp_packet bad request %x len %d seq %x key %x\n",
171 rd->hdr.request, rd->hdr.len, rd->hdr.seq, rd->hdr.key);
172
173 return (FALSE);
174 }
175
176 ret = ((*dispatch_table[req - KDP_CONNECT])(rd, len, reply_port));
177 #if DO_ALIGN
178 bcopy((char *)rd, (char *) pkt, *len);
179 #endif
180 return ret;
181 }
182
183 static boolean_t
184 kdp_unknown(
185 kdp_pkt_t *pkt,
186 __unused int *len,
187 __unused unsigned short *reply_port
188 )
189 {
190 kdp_pkt_t *rd = (kdp_pkt_t *)pkt;
191
192 printf("kdp_unknown request %x len %d seq %x key %x\n",
193 rd->hdr.request, rd->hdr.len, rd->hdr.seq, rd->hdr.key);
194
195 return (FALSE);
196 }
197
198 static boolean_t
199 kdp_connect(
200 kdp_pkt_t *pkt,
201 int *len,
202 unsigned short *reply_port
203 )
204 {
205 kdp_connect_req_t *rq = &pkt->connect_req;
206 size_t plen = *len;
207 kdp_connect_reply_t *rp = &pkt->connect_reply;
208 uint16_t rport, eport;
209 uint32_t key;
210 uint8_t seq;
211
212 if (plen < sizeof (*rq))
213 return (FALSE);
214
215 dprintf(("kdp_connect seq %x greeting %s\n", rq->hdr.seq, rq->greeting));
216
217 rport = rq->req_reply_port;
218 eport = rq->exc_note_port;
219 key = rq->hdr.key;
220 seq = rq->hdr.seq;
221 if (kdp.is_conn) {
222 if ((seq == kdp.conn_seq) && /* duplicate request */
223 (rport == kdp.reply_port) &&
224 (eport == kdp.exception_port) &&
225 (key == kdp.session_key))
226 rp->error = KDPERR_NO_ERROR;
227 else
228 rp->error = KDPERR_ALREADY_CONNECTED;
229 }
230 else {
231 kdp.reply_port = rport;
232 kdp.exception_port = eport;
233 kdp.is_conn = TRUE;
234 kdp.conn_seq = seq;
235 kdp.session_key = key;
236
237 rp->error = KDPERR_NO_ERROR;
238 }
239
240 rp->hdr.is_reply = 1;
241 rp->hdr.len = sizeof (*rp);
242
243 *reply_port = rport;
244 *len = rp->hdr.len;
245
246 if (current_debugger == KDP_CUR_DB)
247 active_debugger=1;
248
249 return (TRUE);
250 }
251
252 static boolean_t
253 kdp_disconnect(
254 kdp_pkt_t *pkt,
255 int *len,
256 unsigned short *reply_port
257 )
258 {
259 kdp_disconnect_req_t *rq = &pkt->disconnect_req;
260 size_t plen = *len;
261 kdp_disconnect_reply_t *rp = &pkt->disconnect_reply;
262
263 if (plen < sizeof (*rq))
264 return (FALSE);
265
266 if (!kdp.is_conn)
267 return (FALSE);
268
269 dprintf(("kdp_disconnect\n"));
270
271 *reply_port = kdp.reply_port;
272
273 kdp.reply_port = kdp.exception_port = 0;
274 kdp.is_halted = kdp.is_conn = FALSE;
275 kdp.exception_seq = kdp.conn_seq = 0;
276 kdp.session_key = 0;
277
278 if (debugger_panic_str != NULL)
279 reattach_wait = 1;
280
281 if (noresume_on_disconnect == 1) {
282 reattach_wait = 1;
283 noresume_on_disconnect = 0;
284 }
285
286 rp->hdr.is_reply = 1;
287 rp->hdr.len = sizeof (*rp);
288
289 *len = rp->hdr.len;
290
291 if (current_debugger == KDP_CUR_DB)
292 active_debugger=0;
293
294 return (TRUE);
295 }
296
297 static boolean_t
298 kdp_reattach(
299 kdp_pkt_t *pkt,
300 int *len,
301 unsigned short *reply_port
302 )
303 {
304 kdp_reattach_req_t *rq = &pkt->reattach_req;
305
306 kdp.is_conn = TRUE;
307 kdp_disconnect(pkt, len, reply_port);
308 *reply_port = rq->req_reply_port;
309 reattach_wait = 1;
310 return (TRUE);
311 }
312
313 static boolean_t
314 kdp_hostinfo(
315 kdp_pkt_t *pkt,
316 int *len,
317 unsigned short *reply_port
318 )
319 {
320 kdp_hostinfo_req_t *rq = &pkt->hostinfo_req;
321 size_t plen = *len;
322 kdp_hostinfo_reply_t *rp = &pkt->hostinfo_reply;
323
324 if (plen < sizeof (*rq))
325 return (FALSE);
326
327 dprintf(("kdp_hostinfo\n"));
328
329 rp->hdr.is_reply = 1;
330 rp->hdr.len = sizeof (*rp);
331
332 kdp_machine_hostinfo(&rp->hostinfo);
333
334 *reply_port = kdp.reply_port;
335 *len = rp->hdr.len;
336
337 return (TRUE);
338 }
339
340 static boolean_t
341 kdp_kernelversion(
342 kdp_pkt_t *pkt,
343 int *len,
344 unsigned short *reply_port
345 )
346 {
347 kdp_kernelversion_req_t *rq = &pkt->kernelversion_req;
348 size_t plen = *len;
349 kdp_kernelversion_reply_t *rp = &pkt->kernelversion_reply;
350 size_t slen;
351
352 if (plen < sizeof (*rq))
353 return (FALSE);
354
355 rp->hdr.is_reply = 1;
356 rp->hdr.len = sizeof (*rp);
357
358 dprintf(("kdp_kernelversion\n"));
359 slen = strlcpy(rp->version, kdp_kernelversion_string, MAX_KDP_DATA_SIZE);
360
361 rp->hdr.len += slen + 1; /* strlcpy returns the amount copied with NUL */
362
363 *reply_port = kdp.reply_port;
364 *len = rp->hdr.len;
365
366 return (TRUE);
367 }
368
369 static boolean_t
370 kdp_suspend(
371 kdp_pkt_t *pkt,
372 int *len,
373 unsigned short *reply_port
374 )
375 {
376 kdp_suspend_req_t *rq = &pkt->suspend_req;
377 size_t plen = *len;
378 kdp_suspend_reply_t *rp = &pkt->suspend_reply;
379
380 if (plen < sizeof (*rq))
381 return (FALSE);
382
383 rp->hdr.is_reply = 1;
384 rp->hdr.len = sizeof (*rp);
385
386 dprintf(("kdp_suspend\n"));
387
388 kdp.is_halted = TRUE;
389
390 *reply_port = kdp.reply_port;
391 *len = rp->hdr.len;
392
393 return (TRUE);
394 }
395
396 static boolean_t
397 kdp_resumecpus(
398 kdp_pkt_t *pkt,
399 int *len,
400 unsigned short *reply_port
401 )
402 {
403 kdp_resumecpus_req_t *rq = &pkt->resumecpus_req;
404 size_t plen = *len;
405 kdp_resumecpus_reply_t *rp = &pkt->resumecpus_reply;
406
407 if (plen < sizeof (*rq))
408 return (FALSE);
409
410 rp->hdr.is_reply = 1;
411 rp->hdr.len = sizeof (*rp);
412
413 dprintf(("kdp_resumecpus %x\n", rq->cpu_mask));
414
415 kdp.is_halted = FALSE;
416
417 *reply_port = kdp.reply_port;
418 *len = rp->hdr.len;
419
420 return (TRUE);
421 }
422
423 static boolean_t
424 kdp_writemem(
425 kdp_pkt_t *pkt,
426 int *len,
427 unsigned short *reply_port
428 )
429 {
430 kdp_writemem_req_t *rq = &pkt->writemem_req;
431 size_t plen = *len;
432 kdp_writemem_reply_t *rp = &pkt->writemem_reply;
433 mach_vm_size_t cnt;
434
435 if (plen < sizeof (*rq))
436 return (FALSE);
437
438 if (rq->nbytes > MAX_KDP_DATA_SIZE)
439 rp->error = KDPERR_BAD_NBYTES;
440 else {
441 dprintf(("kdp_writemem addr %x size %d\n", rq->address, rq->nbytes));
442 cnt = kdp_machine_vm_write((caddr_t)rq->data, (mach_vm_address_t)rq->address, rq->nbytes);
443 rp->error = KDPERR_ACCESS(rq->nbytes, cnt);
444 dprintf((" cnt %lld error %d\n", cnt, rp->error));
445 }
446
447 rp->hdr.is_reply = 1;
448 rp->hdr.len = sizeof (*rp);
449
450 *reply_port = kdp.reply_port;
451 *len = rp->hdr.len;
452
453 return (TRUE);
454 }
455
456 static boolean_t
457 kdp_writemem64(
458 kdp_pkt_t *pkt,
459 int *len,
460 unsigned short *reply_port
461 )
462 {
463 kdp_writemem64_req_t *rq = &pkt->writemem64_req;
464 size_t plen = *len;
465 kdp_writemem64_reply_t *rp = &pkt->writemem64_reply;
466 mach_vm_size_t cnt;
467
468 if (plen < sizeof (*rq))
469 return (FALSE);
470
471 if (rq->nbytes > MAX_KDP_DATA_SIZE)
472 rp->error = KDPERR_BAD_NBYTES;
473 else {
474 dprintf(("kdp_writemem64 addr %llx size %d\n", rq->address, rq->nbytes));
475 cnt = kdp_machine_vm_write((caddr_t)rq->data, (mach_vm_address_t)rq->address, (mach_vm_size_t)rq->nbytes);
476 rp->error = KDPERR_ACCESS(rq->nbytes, cnt);
477 dprintf((" cnt %lld error %d\n", cnt, rp->error));
478 }
479
480 rp->hdr.is_reply = 1;
481 rp->hdr.len = sizeof (*rp);
482
483 *reply_port = kdp.reply_port;
484 *len = rp->hdr.len;
485
486 return (TRUE);
487 }
488
489 static boolean_t
490 kdp_writephysmem64(
491 kdp_pkt_t *pkt,
492 int *len,
493 unsigned short *reply_port
494 )
495 {
496 kdp_writephysmem64_req_t *rq = &pkt->writephysmem64_req;
497 size_t plen = *len;
498 kdp_writephysmem64_reply_t *rp = &pkt->writephysmem64_reply;
499 mach_vm_size_t cnt;
500 unsigned int size;
501
502 if (plen < sizeof (*rq))
503 return (FALSE);
504
505 size = rq->nbytes;
506 if (size > MAX_KDP_DATA_SIZE)
507 rp->error = KDPERR_BAD_NBYTES;
508 else {
509 dprintf(("kdp_writephysmem64 addr %llx size %d\n", rq->address, size));
510 cnt = kdp_machine_phys_write(rq, rq->data, rq->lcpu);
511 rp->error = KDPERR_ACCESS(size, cnt);
512 dprintf((" cnt %lld error %d\n", cnt, rp->error));
513 }
514
515 rp->hdr.is_reply = 1;
516 rp->hdr.len = sizeof (*rp);
517
518 *reply_port = kdp.reply_port;
519 *len = rp->hdr.len;
520
521 return (TRUE);
522 }
523
524 static boolean_t
525 kdp_readmem(
526 kdp_pkt_t *pkt,
527 int *len,
528 unsigned short *reply_port
529 )
530 {
531 kdp_readmem_req_t *rq = &pkt->readmem_req;
532 size_t plen = *len;
533 kdp_readmem_reply_t *rp = &pkt->readmem_reply;
534 mach_vm_size_t cnt;
535 unsigned int size;
536
537 if (plen < sizeof (*rq))
538 return (FALSE);
539
540 rp->hdr.is_reply = 1;
541 rp->hdr.len = sizeof (*rp);
542
543 size = rq->nbytes;
544 if (size > MAX_KDP_DATA_SIZE)
545 rp->error = KDPERR_BAD_NBYTES;
546 else {
547 dprintf(("kdp_readmem addr %x size %d\n", rq->address, size));
548 cnt = kdp_machine_vm_read((mach_vm_address_t)rq->address, (caddr_t)rp->data, rq->nbytes);
549 rp->error = KDPERR_ACCESS(size, cnt);
550 dprintf((" cnt %lld error %d\n", cnt, rp->error));
551
552 rp->hdr.len += cnt;
553 }
554
555 *reply_port = kdp.reply_port;
556 *len = rp->hdr.len;
557
558 return (TRUE);
559 }
560
561 static boolean_t
562 kdp_readmem64(
563 kdp_pkt_t *pkt,
564 int *len,
565 unsigned short *reply_port
566 )
567 {
568 kdp_readmem64_req_t *rq = &pkt->readmem64_req;
569 size_t plen = *len;
570 kdp_readmem64_reply_t *rp = &pkt->readmem64_reply;
571 mach_vm_size_t cnt;
572 unsigned int size;
573
574 if (plen < sizeof (*rq))
575 return (FALSE);
576
577 rp->hdr.is_reply = 1;
578 rp->hdr.len = sizeof (*rp);
579
580 size = rq->nbytes;
581 if (size > MAX_KDP_DATA_SIZE)
582 rp->error = KDPERR_BAD_NBYTES;
583 else {
584 dprintf(("kdp_readmem64 addr %llx size %d\n", rq->address, size));
585 cnt = kdp_machine_vm_read((mach_vm_address_t)rq->address, (caddr_t)rp->data, rq->nbytes);
586 rp->error = KDPERR_ACCESS(size, cnt);
587 dprintf((" cnt %lld error %d\n", cnt, rp->error));
588
589 rp->hdr.len += cnt;
590 }
591
592 *reply_port = kdp.reply_port;
593 *len = rp->hdr.len;
594
595 return (TRUE);
596 }
597
598 static boolean_t
599 kdp_readphysmem64(
600 kdp_pkt_t *pkt,
601 int *len,
602 unsigned short *reply_port
603 )
604 {
605 kdp_readphysmem64_req_t *rq = &pkt->readphysmem64_req;
606 size_t plen = *len;
607 kdp_readphysmem64_reply_t *rp = &pkt->readphysmem64_reply;
608 mach_vm_size_t cnt;
609 unsigned int size;
610
611 if (plen < sizeof (*rq))
612 return (FALSE);
613
614 rp->hdr.is_reply = 1;
615 rp->hdr.len = sizeof (*rp);
616
617 size = rq->nbytes;
618 if (size > MAX_KDP_DATA_SIZE)
619 rp->error = KDPERR_BAD_NBYTES;
620 else {
621 dprintf(("kdp_readphysmem64 addr %llx size %d\n", rq->address, size));
622 cnt = kdp_machine_phys_read(rq, rp->data, rq->lcpu);
623 rp->error = KDPERR_ACCESS(size, cnt);
624 dprintf((" cnt %lld error %d\n", cnt, rp->error));
625
626 rp->hdr.len += cnt;
627 }
628
629 *reply_port = kdp.reply_port;
630 *len = rp->hdr.len;
631
632 return (TRUE);
633 }
634
635 static boolean_t
636 kdp_maxbytes(
637 kdp_pkt_t *pkt,
638 int *len,
639 unsigned short *reply_port
640 )
641 {
642 kdp_maxbytes_req_t *rq = &pkt->maxbytes_req;
643 size_t plen = *len;
644 kdp_maxbytes_reply_t *rp = &pkt->maxbytes_reply;
645
646 if (plen < sizeof (*rq))
647 return (FALSE);
648
649 rp->hdr.is_reply = 1;
650 rp->hdr.len = sizeof (*rp);
651
652 dprintf(("kdp_maxbytes\n"));
653
654 rp->max_bytes = MAX_KDP_DATA_SIZE;
655
656 *reply_port = kdp.reply_port;
657 *len = rp->hdr.len;
658
659 return (TRUE);
660 }
661
662 static boolean_t
663 kdp_version(
664 kdp_pkt_t *pkt,
665 int *len,
666 unsigned short *reply_port
667 )
668 {
669 kdp_version_req_t *rq = &pkt->version_req;
670 size_t plen = *len;
671 kdp_version_reply_t *rp = &pkt->version_reply;
672
673 if (plen < sizeof (*rq))
674 return (FALSE);
675
676 rp->hdr.is_reply = 1;
677 rp->hdr.len = sizeof (*rp);
678
679 dprintf(("kdp_version\n"));
680
681 rp->version = KDP_VERSION;
682 if (!(kdp_flag & KDP_BP_DIS))
683 rp->feature = KDP_FEATURE_BP;
684 else
685 rp->feature = 0;
686
687 *reply_port = kdp.reply_port;
688 *len = rp->hdr.len;
689
690 return (TRUE);
691 }
692
693 static boolean_t
694 kdp_regions(
695 kdp_pkt_t *pkt,
696 int *len,
697 unsigned short *reply_port
698 )
699 {
700 kdp_regions_req_t *rq = &pkt->regions_req;
701 size_t plen = *len;
702 kdp_regions_reply_t *rp = &pkt->regions_reply;
703 kdp_region_t *r;
704
705 if (plen < sizeof (*rq))
706 return (FALSE);
707
708 rp->hdr.is_reply = 1;
709 rp->hdr.len = sizeof (*rp);
710
711 dprintf(("kdp_regions\n"));
712
713 r = rp->regions;
714 rp->nregions = 0;
715
716 r->address = 0;
717 r->nbytes = 0xffffffff;
718
719 r->protection = VM_PROT_ALL; r++; rp->nregions++;
720
721 rp->hdr.len += rp->nregions * sizeof (kdp_region_t);
722
723 *reply_port = kdp.reply_port;
724 *len = rp->hdr.len;
725
726 return (TRUE);
727 }
728
729 static boolean_t
730 kdp_writeregs(
731 kdp_pkt_t *pkt,
732 int *len,
733 unsigned short *reply_port
734 )
735 {
736 kdp_writeregs_req_t *rq = &pkt->writeregs_req;
737 size_t plen = *len;
738 int size;
739 kdp_writeregs_reply_t *rp = &pkt->writeregs_reply;
740
741 if (plen < sizeof (*rq))
742 return (FALSE);
743
744 size = rq->hdr.len - (unsigned)sizeof(kdp_hdr_t) - (unsigned)sizeof(unsigned int);
745 rp->error = kdp_machine_write_regs(rq->cpu, rq->flavor, rq->data, &size);
746
747 rp->hdr.is_reply = 1;
748 rp->hdr.len = sizeof (*rp);
749
750 *reply_port = kdp.reply_port;
751 *len = rp->hdr.len;
752
753 return (TRUE);
754 }
755
756 static boolean_t
757 kdp_readregs(
758 kdp_pkt_t *pkt,
759 int *len,
760 unsigned short *reply_port
761 )
762 {
763 kdp_readregs_req_t *rq = &pkt->readregs_req;
764 size_t plen = *len;
765 kdp_readregs_reply_t *rp = &pkt->readregs_reply;
766 int size;
767
768 if (plen < sizeof (*rq))
769 return (FALSE);
770
771 rp->hdr.is_reply = 1;
772 rp->hdr.len = sizeof (*rp);
773
774 rp->error = kdp_machine_read_regs(rq->cpu, rq->flavor, rp->data, &size);
775 rp->hdr.len += size;
776
777 *reply_port = kdp.reply_port;
778 *len = rp->hdr.len;
779
780 return (TRUE);
781 }
782
783
784 boolean_t
785 kdp_breakpoint_set(
786 kdp_pkt_t *pkt,
787 int *len,
788 unsigned short *reply_port
789 )
790 {
791 kdp_breakpoint_req_t *rq = &pkt->breakpoint_req;
792 kdp_breakpoint_reply_t *rp = &pkt->breakpoint_reply;
793 size_t plen = *len;
794 kdp_error_t kerr;
795
796 if (plen < sizeof (*rq))
797 return (FALSE);
798
799 dprintf(("kdp_breakpoint_set %x\n", rq->address));
800
801 kerr = kdp_set_breakpoint_internal((mach_vm_address_t)rq->address);
802
803 rp->error = kerr;
804
805 rp->hdr.is_reply = 1;
806 rp->hdr.len = sizeof (*rp);
807 *reply_port = kdp.reply_port;
808 *len = rp->hdr.len;
809
810 return (TRUE);
811 }
812
813 boolean_t
814 kdp_breakpoint64_set(
815 kdp_pkt_t *pkt,
816 int *len,
817 unsigned short *reply_port
818 )
819 {
820 kdp_breakpoint64_req_t *rq = &pkt->breakpoint64_req;
821 kdp_breakpoint64_reply_t *rp = &pkt->breakpoint64_reply;
822 size_t plen = *len;
823 kdp_error_t kerr;
824
825 if (plen < sizeof (*rq))
826 return (FALSE);
827
828 dprintf(("kdp_breakpoint64_set %llx\n", rq->address));
829
830 kerr = kdp_set_breakpoint_internal((mach_vm_address_t)rq->address);
831
832 rp->error = kerr;
833
834 rp->hdr.is_reply = 1;
835 rp->hdr.len = sizeof (*rp);
836 *reply_port = kdp.reply_port;
837 *len = rp->hdr.len;
838
839 return (TRUE);
840 }
841
842 boolean_t
843 kdp_breakpoint_remove(
844 kdp_pkt_t *pkt,
845 int *len,
846 unsigned short *reply_port
847 )
848 {
849 kdp_breakpoint_req_t *rq = &pkt->breakpoint_req;
850 kdp_breakpoint_reply_t *rp = &pkt->breakpoint_reply;
851 size_t plen = *len;
852 kdp_error_t kerr;
853 if (plen < sizeof (*rq))
854 return (FALSE);
855
856 dprintf(("kdp_breakpoint_remove %x\n", rq->address));
857
858 kerr = kdp_remove_breakpoint_internal((mach_vm_address_t)rq->address);
859
860 rp->error = kerr;
861
862 rp->hdr.is_reply = 1;
863 rp->hdr.len = sizeof (*rp);
864 *reply_port = kdp.reply_port;
865 *len = rp->hdr.len;
866
867 return (TRUE);
868 }
869
870 boolean_t
871 kdp_breakpoint64_remove(
872 kdp_pkt_t *pkt,
873 int *len,
874 unsigned short *reply_port
875 )
876 {
877 kdp_breakpoint64_req_t *rq = &pkt->breakpoint64_req;
878 kdp_breakpoint64_reply_t *rp = &pkt->breakpoint64_reply;
879 size_t plen = *len;
880 kdp_error_t kerr;
881
882 if (plen < sizeof (*rq))
883 return (FALSE);
884
885 dprintf(("kdp_breakpoint64_remove %llx\n", rq->address));
886
887 kerr = kdp_remove_breakpoint_internal((mach_vm_address_t)rq->address);
888
889 rp->error = kerr;
890
891 rp->hdr.is_reply = 1;
892 rp->hdr.len = sizeof (*rp);
893 *reply_port = kdp.reply_port;
894 *len = rp->hdr.len;
895
896 return (TRUE);
897 }
898
899
900 kdp_error_t
901 kdp_set_breakpoint_internal(
902 mach_vm_address_t address
903 )
904 {
905
906 uint8_t breakinstr[MAX_BREAKINSN_BYTES], oldinstr[MAX_BREAKINSN_BYTES];
907 uint32_t breakinstrsize = sizeof(breakinstr);
908 mach_vm_size_t cnt;
909 int i;
910
911 kdp_machine_get_breakinsn(breakinstr, &breakinstrsize);
912
913 if(breakpoints_initialized == 0)
914 {
915 for(i=0;(i < MAX_BREAKPOINTS); breakpoint_list[i].address=0, i++);
916 breakpoints_initialized++;
917 }
918
919 cnt = kdp_machine_vm_read(address, (caddr_t)&oldinstr, (mach_vm_size_t)breakinstrsize);
920
921 if (0 == memcmp(oldinstr, breakinstr, breakinstrsize)) {
922 printf("A trap was already set at that address, not setting new breakpoint\n");
923
924 return KDPERR_BREAKPOINT_ALREADY_SET;
925 }
926
927 for(i=0;(i < MAX_BREAKPOINTS) && (breakpoint_list[i].address != 0); i++);
928
929 if (i == MAX_BREAKPOINTS) {
930 return KDPERR_MAX_BREAKPOINTS;
931 }
932
933 breakpoint_list[i].address = address;
934 memcpy(breakpoint_list[i].oldbytes, oldinstr, breakinstrsize);
935 breakpoint_list[i].bytesused = breakinstrsize;
936
937 cnt = kdp_machine_vm_write((caddr_t)&breakinstr, address, breakinstrsize);
938
939 return KDPERR_NO_ERROR;
940 }
941
942 kdp_error_t
943 kdp_remove_breakpoint_internal(
944 mach_vm_address_t address
945 )
946 {
947 mach_vm_size_t cnt;
948 int i;
949
950 for(i=0;(i < MAX_BREAKPOINTS) && (breakpoint_list[i].address != address); i++);
951
952 if (i == MAX_BREAKPOINTS)
953 {
954 return KDPERR_BREAKPOINT_NOT_FOUND;
955 }
956
957 breakpoint_list[i].address = 0;
958 cnt = kdp_machine_vm_write((caddr_t)&breakpoint_list[i].oldbytes, address, breakpoint_list[i].bytesused);
959
960 return KDPERR_NO_ERROR;
961 }
962
963 boolean_t
964 kdp_remove_all_breakpoints(void)
965 {
966 int i;
967 boolean_t breakpoint_found = FALSE;
968
969 if (breakpoints_initialized)
970 {
971 for(i=0;i < MAX_BREAKPOINTS; i++)
972 {
973 if (breakpoint_list[i].address)
974 {
975 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);
976 breakpoint_found = TRUE;
977 breakpoint_list[i].address = 0;
978 }
979 }
980
981 if (breakpoint_found)
982 printf("kdp_remove_all_breakpoints: found extant breakpoints, removing them.\n");
983 }
984 return breakpoint_found;
985 }
986
987 boolean_t
988 kdp_reboot(
989 __unused kdp_pkt_t *pkt,
990 __unused int *len,
991 __unused unsigned short *reply_port
992 )
993 {
994 dprintf(("kdp_reboot\n"));
995
996 kdp_machine_reboot();
997
998 return (TRUE); // no, not really, we won't return
999 }
1000
1001 static boolean_t
1002 kdp_readioport(
1003 kdp_pkt_t *pkt,
1004 int *len,
1005 unsigned short *reply_port
1006 )
1007 {
1008 kdp_readioport_req_t *rq = &pkt->readioport_req;
1009 kdp_readioport_reply_t *rp = &pkt->readioport_reply;
1010 size_t plen = *len;
1011
1012 if (plen < sizeof (*rq))
1013 return (FALSE);
1014
1015 rp->hdr.is_reply = 1;
1016 rp->hdr.len = sizeof (*rp);
1017
1018 if (rq->nbytes > MAX_KDP_DATA_SIZE)
1019 rp->error = KDPERR_BAD_NBYTES;
1020 else {
1021 #if KDP_TEST_HARNESS
1022 uint16_t addr = rq->address;
1023 #endif
1024 uint16_t size = rq->nbytes;
1025 dprintf(("kdp_readioport addr %x size %d\n", addr, size));
1026
1027 rp->error = kdp_machine_ioport_read(rq, rp->data, rq->lcpu);
1028 if (rp->error == KDPERR_NO_ERROR)
1029 rp->hdr.len += size;
1030 }
1031
1032 *reply_port = kdp.reply_port;
1033 *len = rp->hdr.len;
1034
1035 return (TRUE);
1036 }
1037
1038 static boolean_t
1039 kdp_writeioport(
1040 kdp_pkt_t *pkt,
1041 int *len,
1042 unsigned short *reply_port
1043 )
1044 {
1045 kdp_writeioport_req_t *rq = &pkt->writeioport_req;
1046 kdp_writeioport_reply_t *rp = &pkt->writeioport_reply;
1047 size_t plen = *len;
1048
1049 if (plen < sizeof (*rq))
1050 return (FALSE);
1051
1052 if (rq->nbytes > MAX_KDP_DATA_SIZE)
1053 rp->error = KDPERR_BAD_NBYTES;
1054 else {
1055 dprintf(("kdp_writeioport addr %x size %d\n", rq->address,
1056 rq->nbytes));
1057
1058 rp->error = kdp_machine_ioport_write(rq, rq->data, rq->lcpu);
1059 }
1060
1061 rp->hdr.is_reply = 1;
1062 rp->hdr.len = sizeof (*rp);
1063
1064 *reply_port = kdp.reply_port;
1065 *len = rp->hdr.len;
1066
1067 return (TRUE);
1068 }
1069
1070 static boolean_t
1071 kdp_readmsr64(
1072 kdp_pkt_t *pkt,
1073 int *len,
1074 unsigned short *reply_port
1075 )
1076 {
1077 kdp_readmsr64_req_t *rq = &pkt->readmsr64_req;
1078 kdp_readmsr64_reply_t *rp = &pkt->readmsr64_reply;
1079 size_t plen = *len;
1080
1081 if (plen < sizeof (*rq))
1082 return (FALSE);
1083
1084 rp->hdr.is_reply = 1;
1085 rp->hdr.len = sizeof (*rp);
1086
1087 dprintf(("kdp_readmsr64 lcpu %x addr %x\n", rq->lcpu, rq->address));
1088 rp->error = kdp_machine_msr64_read(rq, rp->data, rq->lcpu);
1089 if (rp->error == KDPERR_NO_ERROR)
1090 rp->hdr.len += sizeof(uint64_t);
1091
1092 *reply_port = kdp.reply_port;
1093 *len = rp->hdr.len;
1094
1095 return (TRUE);
1096 }
1097
1098 static boolean_t
1099 kdp_writemsr64(
1100 kdp_pkt_t *pkt,
1101 int *len,
1102 unsigned short *reply_port
1103 )
1104 {
1105 kdp_writemsr64_req_t *rq = &pkt->writemsr64_req;
1106 kdp_writemsr64_reply_t *rp = &pkt->writemsr64_reply;
1107 size_t plen = *len;
1108
1109 if (plen < sizeof (*rq))
1110 return (FALSE);
1111
1112 dprintf(("kdp_writemsr64 lcpu %x addr %x\n", rq->lcpu, rq->address));
1113 rp->error = kdp_machine_msr64_write(rq, rq->data, rq->lcpu);
1114
1115 rp->hdr.is_reply = 1;
1116 rp->hdr.len = sizeof (*rp);
1117
1118 *reply_port = kdp.reply_port;
1119 *len = rp->hdr.len;
1120
1121 return (TRUE);
1122 }
1123
1124 static boolean_t
1125 kdp_dumpinfo(
1126 kdp_pkt_t *pkt,
1127 int *len,
1128 unsigned short *reply_port
1129 )
1130 {
1131 kdp_dumpinfo_req_t *rq = &pkt->dumpinfo_req;
1132 kdp_dumpinfo_reply_t *rp = &pkt->dumpinfo_reply;
1133 size_t plen = *len;
1134
1135 if (plen < sizeof (*rq))
1136 return (FALSE);
1137
1138 dprintf(("kdp_dumpinfo file=%s destip=%s routerip=%s\n", rq->name, rq->destip, rq->routerip));
1139 rp->hdr.is_reply = 1;
1140 rp->hdr.len = sizeof (*rp);
1141
1142 if ((rq->type & KDP_DUMPINFO_MASK) != KDP_DUMPINFO_GETINFO) {
1143 kdp_set_dump_info(rq->type, rq->name, rq->destip, rq->routerip,
1144 rq->port);
1145 }
1146
1147 /* gather some stats for reply */
1148 kdp_get_dump_info(rp);
1149
1150 *reply_port = kdp.reply_port;
1151 *len = rp->hdr.len;
1152
1153 return (TRUE);
1154 }
1155