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