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