]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kdp/kdp.c
xnu-4903.221.2.tar.gz
[apple/xnu.git] / osfmk / kdp / kdp.c
CommitLineData
1c79356b 1/*
39236c6e 2 * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b 27 */
1c79356b
A
28
29#include <mach/mach_types.h>
316670eb 30#include <mach/vm_param.h>
b0d623f7 31#include <sys/appleapiopts.h>
1c79356b 32#include <kern/debug.h>
b7266188 33#include <uuid/uuid.h>
1c79356b
A
34
35#include <kdp/kdp_internal.h>
36#include <kdp/kdp_private.h>
7e4a7d39 37#include <kdp/kdp_core.h>
1c79356b 38
9bccf70c 39#include <libsa/types.h>
6d2010ae 40#include <libkern/version.h>
9bccf70c 41
91447636
A
42#include <string.h> /* bcopy */
43
0c530ab8
A
44#include <kern/processor.h>
45#include <kern/thread.h>
6d2010ae 46#include <kern/clock.h>
0c530ab8
A
47#include <vm/vm_map.h>
48#include <vm/vm_kern.h>
316670eb 49#include <vm/vm_pageout.h>
39236c6e
A
50#include <vm/vm_shared_region.h>
51#include <libkern/OSKextLibPrivate.h>
316670eb 52
1c79356b
A
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
62static kdp_dispatch_t
b0d623f7 63 dispatch_table[KDP_INVALID_REQUEST-KDP_CONNECT] =
1c79356b
A
64 {
65/* 0 */ kdp_connect,
66/* 1 */ kdp_disconnect,
67/* 2 */ kdp_hostinfo,
9bccf70c 68/* 3 */ kdp_version,
1c79356b
A
69/* 4 */ kdp_maxbytes,
70/* 5 */ kdp_readmem,
71/* 6 */ kdp_writemem,
72/* 7 */ kdp_readregs,
73/* 8 */ kdp_writeregs,
9bccf70c
A
74/* 9 */ kdp_unknown,
75/* A */ kdp_unknown,
1c79356b
A
76/* B */ kdp_suspend,
77/* C */ kdp_resumecpus,
78/* D */ kdp_unknown,
9bccf70c
A
79/* E */ kdp_unknown,
80/* F */ kdp_breakpoint_set,
81/*10 */ kdp_breakpoint_remove,
82/*11 */ kdp_regions,
91447636 83/*12 */ kdp_reattach,
b0d623f7
A
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,
7e4a7d39
A
91/*1A */ kdp_writephysmem64,
92/*1B */ kdp_readioport,
93/*1C */ kdp_writeioport,
94/*1D */ kdp_readmsr64,
95/*1E */ kdp_writemsr64,
96/*1F */ kdp_dumpinfo,
1c79356b
A
97 };
98
99kdp_glob_t kdp;
9bccf70c 100
9bccf70c 101#define MAX_BREAKPOINTS 100
9bccf70c 102
b0d623f7
A
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
7e4a7d39 107 * memory with 64-bit wide memory addresses.
b0d623f7
A
108 */
109#define KDP_VERSION 12
9bccf70c
A
110
111typedef struct{
b0d623f7
A
112 mach_vm_address_t address;
113 uint32_t bytesused;
114 uint8_t oldbytes[MAX_BREAKINSN_BYTES];
9bccf70c
A
115} kdp_breakpoint_record_t;
116
117static kdp_breakpoint_record_t breakpoint_list[MAX_BREAKPOINTS];
118static unsigned int breakpoints_initialized = 0;
55e303ae 119
9bccf70c 120int reattach_wait = 0;
55e303ae 121int noresume_on_disconnect = 0;
1c79356b 122
b0d623f7
A
123kdp_error_t
124kdp_set_breakpoint_internal(
125 mach_vm_address_t address
126 );
127
128kdp_error_t
129kdp_remove_breakpoint_internal(
130 mach_vm_address_t address
131 );
132
1c79356b
A
133boolean_t
134kdp_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;
2d21ac55
A
142 size_t plen = *len;
143 kdp_req_t req;
1c79356b 144 boolean_t ret;
39037602 145
1c79356b 146#if DO_ALIGN
39037602
A
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);
1c79356b
A
152#else
153 rd = (kdp_pkt_t *)pkt;
154#endif
155 if (plen < sizeof (rd->hdr) || rd->hdr.len != plen) {
2d21ac55 156 printf("kdp_packet bad len pkt %lu hdr %d\n", plen, rd->hdr.len);
1c79356b
A
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;
b0d623f7 169 if (req >= KDP_INVALID_REQUEST) {
1c79356b
A
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
183static boolean_t
184kdp_unknown(
185 kdp_pkt_t *pkt,
2d21ac55
A
186 __unused int *len,
187 __unused unsigned short *reply_port
1c79356b
A
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
198static boolean_t
199kdp_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;
2d21ac55 206 size_t plen = *len;
1c79356b 207 kdp_connect_reply_t *rp = &pkt->connect_reply;
7e4a7d39
A
208 uint16_t rport, eport;
209 uint32_t key;
210 uint8_t seq;
1c79356b
A
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
7e4a7d39
A
217 rport = rq->req_reply_port;
218 eport = rq->exc_note_port;
219 key = rq->hdr.key;
220 seq = rq->hdr.seq;
1c79356b 221 if (kdp.is_conn) {
7e4a7d39
A
222 if ((seq == kdp.conn_seq) && /* duplicate request */
223 (rport == kdp.reply_port) &&
224 (eport == kdp.exception_port) &&
225 (key == kdp.session_key))
1c79356b 226 rp->error = KDPERR_NO_ERROR;
7e4a7d39 227 else
1c79356b
A
228 rp->error = KDPERR_ALREADY_CONNECTED;
229 }
230 else {
39236c6e
A
231 kdp.reply_port = rport;
232 kdp.exception_port = eport;
233 kdp.is_conn = TRUE;
234 kdp.conn_seq = seq;
7e4a7d39
A
235 kdp.session_key = key;
236
1c79356b
A
237 rp->error = KDPERR_NO_ERROR;
238 }
239
240 rp->hdr.is_reply = 1;
241 rp->hdr.len = sizeof (*rp);
242
7e4a7d39 243 *reply_port = rport;
1c79356b
A
244 *len = rp->hdr.len;
245
246 if (current_debugger == KDP_CUR_DB)
247 active_debugger=1;
248
249 return (TRUE);
250}
251
252static boolean_t
253kdp_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;
2d21ac55 260 size_t plen = *len;
1c79356b
A
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;
7e4a7d39 276 kdp.session_key = 0;
1c79356b 277
5ba3f43e 278 if (debugger_panic_str != NULL)
39236c6e 279 reattach_wait = 1;
2d21ac55 280
55e303ae
A
281 if (noresume_on_disconnect == 1) {
282 reattach_wait = 1;
283 noresume_on_disconnect = 0;
284 }
285
1c79356b
A
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
9bccf70c
A
297static boolean_t
298kdp_reattach(
299 kdp_pkt_t *pkt,
300 int *len,
301 unsigned short *reply_port
302)
303{
39236c6e 304 kdp_reattach_req_t *rq = &pkt->reattach_req;
9bccf70c 305
39236c6e
A
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);
9bccf70c
A
311}
312
1c79356b
A
313static boolean_t
314kdp_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;
2d21ac55 321 size_t plen = *len;
1c79356b
A
322 kdp_hostinfo_reply_t *rp = &pkt->hostinfo_reply;
323
324 if (plen < sizeof (*rq))
325 return (FALSE);
326
39236c6e 327 dprintf(("kdp_hostinfo\n"));
b0d623f7 328
1c79356b
A
329 rp->hdr.is_reply = 1;
330 rp->hdr.len = sizeof (*rp);
331
332 kdp_machine_hostinfo(&rp->hostinfo);
9bccf70c 333
1c79356b
A
334 *reply_port = kdp.reply_port;
335 *len = rp->hdr.len;
336
337 return (TRUE);
338}
339
b0d623f7
A
340static boolean_t
341kdp_kernelversion(
39236c6e
A
342 kdp_pkt_t *pkt,
343 int *len,
344 unsigned short *reply_port
b0d623f7
A
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"));
39236c6e 359 slen = strlcpy(rp->version, kdp_kernelversion_string, MAX_KDP_DATA_SIZE);
b0d623f7 360
39236c6e 361 rp->hdr.len += slen + 1; /* strlcpy returns the amount copied with NUL */
b0d623f7
A
362
363 *reply_port = kdp.reply_port;
364 *len = rp->hdr.len;
365
366 return (TRUE);
367}
368
1c79356b
A
369static boolean_t
370kdp_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;
2d21ac55 377 size_t plen = *len;
1c79356b
A
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
396static boolean_t
397kdp_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;
2d21ac55 404 size_t plen = *len;
1c79356b
A
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));
9bccf70c 414
1c79356b
A
415 kdp.is_halted = FALSE;
416
417 *reply_port = kdp.reply_port;
418 *len = rp->hdr.len;
419
420 return (TRUE);
421}
422
423static boolean_t
424kdp_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;
2d21ac55 431 size_t plen = *len;
1c79356b 432 kdp_writemem_reply_t *rp = &pkt->writemem_reply;
39236c6e 433 mach_vm_size_t cnt;
1c79356b
A
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));
b0d623f7 442 cnt = kdp_machine_vm_write((caddr_t)rq->data, (mach_vm_address_t)rq->address, rq->nbytes);
39236c6e
A
443 rp->error = KDPERR_ACCESS(rq->nbytes, cnt);
444 dprintf((" cnt %lld error %d\n", cnt, rp->error));
1c79356b
A
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
b0d623f7
A
456static boolean_t
457kdp_writemem64(
39236c6e
A
458 kdp_pkt_t *pkt,
459 int *len,
460 unsigned short *reply_port
b0d623f7
A
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)
39236c6e 472 rp->error = KDPERR_BAD_NBYTES;
b0d623f7 473 else {
39236c6e
A
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));
b0d623f7
A
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
489static boolean_t
490kdp_writephysmem64(
39236c6e
A
491 kdp_pkt_t *pkt,
492 int *len,
493 unsigned short *reply_port
b0d623f7
A
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;
39236c6e
A
499 mach_vm_size_t cnt;
500 unsigned int size;
b0d623f7
A
501
502 if (plen < sizeof (*rq))
39236c6e 503 return (FALSE);
b0d623f7 504
39236c6e
A
505 size = rq->nbytes;
506 if (size > MAX_KDP_DATA_SIZE)
507 rp->error = KDPERR_BAD_NBYTES;
b0d623f7 508 else {
39236c6e
A
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));
b0d623f7
A
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
1c79356b
A
524static boolean_t
525kdp_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;
2d21ac55 532 size_t plen = *len;
1c79356b 533 kdp_readmem_reply_t *rp = &pkt->readmem_reply;
39236c6e
A
534 mach_vm_size_t cnt;
535 unsigned int size;
b0d623f7 536
1c79356b
A
537 if (plen < sizeof (*rq))
538 return (FALSE);
539
540 rp->hdr.is_reply = 1;
541 rp->hdr.len = sizeof (*rp);
542
39236c6e
A
543 size = rq->nbytes;
544 if (size > MAX_KDP_DATA_SIZE)
1c79356b
A
545 rp->error = KDPERR_BAD_NBYTES;
546 else {
39236c6e
A
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));
1c79356b
A
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
b0d623f7
A
561static boolean_t
562kdp_readmem64(
39236c6e
A
563 kdp_pkt_t *pkt,
564 int *len,
565 unsigned short *reply_port
b0d623f7
A
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;
39236c6e
A
571 mach_vm_size_t cnt;
572 unsigned int size;
b0d623f7
A
573
574 if (plen < sizeof (*rq))
575 return (FALSE);
576
577 rp->hdr.is_reply = 1;
578 rp->hdr.len = sizeof (*rp);
579
39236c6e
A
580 size = rq->nbytes;
581 if (size > MAX_KDP_DATA_SIZE)
582 rp->error = KDPERR_BAD_NBYTES;
b0d623f7 583 else {
39236c6e
A
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));
b0d623f7 588
39236c6e 589 rp->hdr.len += cnt;
b0d623f7
A
590 }
591
592 *reply_port = kdp.reply_port;
593 *len = rp->hdr.len;
594
595 return (TRUE);
596}
597
598static boolean_t
599kdp_readphysmem64(
39236c6e
A
600 kdp_pkt_t *pkt,
601 int *len,
602 unsigned short *reply_port
b0d623f7
A
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;
39236c6e
A
608 mach_vm_size_t cnt;
609 unsigned int size;
b0d623f7
A
610
611 if (plen < sizeof (*rq))
39236c6e 612 return (FALSE);
b0d623f7
A
613
614 rp->hdr.is_reply = 1;
615 rp->hdr.len = sizeof (*rp);
616
39236c6e
A
617 size = rq->nbytes;
618 if (size > MAX_KDP_DATA_SIZE)
619 rp->error = KDPERR_BAD_NBYTES;
b0d623f7 620 else {
39236c6e
A
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));
b0d623f7 625
39236c6e 626 rp->hdr.len += cnt;
b0d623f7
A
627 }
628
629 *reply_port = kdp.reply_port;
630 *len = rp->hdr.len;
631
632 return (TRUE);
633}
634
1c79356b
A
635static boolean_t
636kdp_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;
2d21ac55 643 size_t plen = *len;
1c79356b
A
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
9bccf70c
A
662static boolean_t
663kdp_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;
2d21ac55 670 size_t plen = *len;
9bccf70c 671 kdp_version_reply_t *rp = &pkt->version_reply;
9bccf70c
A
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;
9bccf70c
A
682 if (!(kdp_flag & KDP_BP_DIS))
683 rp->feature = KDP_FEATURE_BP;
684 else
685 rp->feature = 0;
b0d623f7 686
9bccf70c
A
687 *reply_port = kdp.reply_port;
688 *len = rp->hdr.len;
689
690 return (TRUE);
691}
692
1c79356b
A
693static boolean_t
694kdp_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;
2d21ac55 701 size_t plen = *len;
1c79356b
A
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
b0d623f7 716 r->address = 0;
1c79356b
A
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
729static boolean_t
730kdp_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;
2d21ac55 737 size_t plen = *len;
1c79356b
A
738 int size;
739 kdp_writeregs_reply_t *rp = &pkt->writeregs_reply;
740
741 if (plen < sizeof (*rq))
742 return (FALSE);
743
b0d623f7 744 size = rq->hdr.len - (unsigned)sizeof(kdp_hdr_t) - (unsigned)sizeof(unsigned int);
1c79356b
A
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
756static boolean_t
757kdp_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;
2d21ac55 764 size_t plen = *len;
1c79356b
A
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}
9bccf70c 782
b0d623f7
A
783
784boolean_t
9bccf70c 785kdp_breakpoint_set(
39236c6e
A
786 kdp_pkt_t *pkt,
787 int *len,
788 unsigned short *reply_port
9bccf70c
A
789)
790{
b0d623f7
A
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));
9bccf70c 800
b0d623f7
A
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}
9bccf70c 812
b0d623f7
A
813boolean_t
814kdp_breakpoint64_set(
39236c6e
A
815 kdp_pkt_t *pkt,
816 int *len,
817 unsigned short *reply_port
b0d623f7
A
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));
9bccf70c 829
b0d623f7
A
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}
9bccf70c 841
b0d623f7
A
842boolean_t
843kdp_breakpoint_remove(
39236c6e
A
844 kdp_pkt_t *pkt,
845 int *len,
846 unsigned short *reply_port
b0d623f7
A
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));
9bccf70c 857
b0d623f7
A
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);
9bccf70c
A
868}
869
b0d623f7
A
870boolean_t
871kdp_breakpoint64_remove(
39236c6e
A
872 kdp_pkt_t *pkt,
873 int *len,
874 unsigned short *reply_port
9bccf70c
A
875)
876{
b0d623f7
A
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));
9bccf70c 886
b0d623f7
A
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}
9bccf70c 898
9bccf70c 899
b0d623f7
A
900kdp_error_t
901kdp_set_breakpoint_internal(
39236c6e
A
902 mach_vm_address_t address
903)
b0d623f7
A
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++;
9bccf70c 917 }
b0d623f7
A
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}
9bccf70c 941
b0d623f7
A
942kdp_error_t
943kdp_remove_breakpoint_internal(
39236c6e
A
944 mach_vm_address_t address
945)
b0d623f7
A
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)
39236c6e 953 {
b0d623f7
A
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;
9bccf70c
A
961}
962
963boolean_t
2d21ac55 964kdp_remove_all_breakpoints(void)
9bccf70c 965{
b0d623f7
A
966 int i;
967 boolean_t breakpoint_found = FALSE;
968
969 if (breakpoints_initialized)
39236c6e 970 {
b0d623f7
A
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");
39236c6e 983 }
b0d623f7 984 return breakpoint_found;
9bccf70c 985}
0c530ab8 986
b0d623f7
A
987boolean_t
988kdp_reboot(
39236c6e
A
989 __unused kdp_pkt_t *pkt,
990 __unused int *len,
991 __unused unsigned short *reply_port
b0d623f7
A
992)
993{
994 dprintf(("kdp_reboot\n"));
995
996 kdp_machine_reboot();
997
998 return (TRUE); // no, not really, we won't return
999}
0c530ab8 1000
b0d623f7 1001static boolean_t
39236c6e
A
1002kdp_readioport(
1003 kdp_pkt_t *pkt,
b0d623f7
A
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
1038static boolean_t
1039kdp_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
1070static boolean_t
39236c6e
A
1071kdp_readmsr64(
1072 kdp_pkt_t *pkt,
1073 int *len,
1074 unsigned short *reply_port
1075)
b0d623f7
A
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
1098static boolean_t
1099kdp_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}
7e4a7d39
A
1123
1124static boolean_t
1125kdp_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 */
813fb2f6 1148 kdp_get_dump_info(rp);
7e4a7d39
A
1149
1150 *reply_port = kdp.reply_port;
1151 *len = rp->hdr.len;
1152
1153 return (TRUE);
1154}
fe8ab488 1155